> For the complete documentation index, see [llms.txt](https://dominik1123.gitbook.io/hanna/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dominik1123.gitbook.io/hanna/groups.md).

# Groups

Parameter groups in general describe associations of multiple parameters and the way they interact with each other. For example:

```python
from hanna import Configurable, Group, Integer

class Rectangle(Configurable):
    dimensions = Group(Integer('width'), Integer('height'))
    
r = Rectangle(dict(width=2, height=3))
r.dimensions  # {'width': 2, 'height': 3}
```

Internally parameter groups are converted to a `dict` with the group member names as keys and their loaded specifications as values.

### Using different containers

By default `Group` uses a `dict` as container for its members (after loading). We can customize this:

```python
from collections import namedtuple

class Rectangle(Configurable):
    dim_type = namedtuple('dimensions', ['width', 'height'])
    dimensions = Group(Integer('width'), Integer('height'), as_=dim_type)
    del dim_type
    
r = Rectangle(dict(width=2, height=3))
r.dimensions  # dimensions(width=2, height=3)
r.dimensions.width, r.dimensions.height  # (2, 3)
```

Any object `obj` that supports `obj(**member_dict)` argument expansion as well as `tuple` and `list` can be used as the containing data structure. For `tuple` and `list` the member names are dropped but the order in which they were declared is maintained.

### Transformations

Transformations can be applied to Groups in a similar way that they are applied to parameters (see [Transformations](/hanna/transformations.md)). For example:

```python
class Rectangle(Configurable):
    area = Group(
        Integer('width'), Integer('height'),
        as_=tuple
    ) >> (lambda x: x[0]*x[1])
    
r = Rectangle(dict(width=2, height=3))
r.area  # 6
```

### Sections

Groups can be assigned to separate sections similar to [Class Sections](/hanna/partitions-sections-namespaces.md#class-sections) but with the difference that the specified section won't be used to modify the members' names but instead to concatenate section and name when loading the parameter. For example:

```python
from pyhocon import ConfigFactory

class Rectangle(Configurable):
    # The `name` keyword argument is used to specify group sections.
    dimensions = Group(Integer('width'), Integer('height'), name='square')
    
r = Rectangle(ConfigFactory.parse_string(
    """square {
            width = 2
            height = 3
        }"""
))
# Section names are not prepended to parameter names.
r.dimensions  # {'width': 2, 'height': 3}
```

### Adding members

Parameters can be add to an existing group in the following ways:

```python
group = Group(Integer('i'))
group += Integer('j')
group.add(Integer('k'))
```

### Extending groups

Existing groups can be extended by others in the following way:

```python
rectangle = Group(Integer('width'), Integer('height'), name='square')
color = Group(Integer('r'), Integer('g'), Integer('b'), name='color')
rectangle.extend(color)
```

When extending a group it retains its original name / section and modifies the names of the other group's parameters by prepending the other group's name / section to the other group's members. Let's have a closer look:

```python
rectangle.name  # "square"
rectangle.members[0].name  # "width"
rectangle.members[-1].name  # "color.b"
```

In order to load the the group we can provide the following HOCON file:

```
square {
    width = 2
    height = 3
    color {
        r = 32
        g = 64
        b = 128
    }
}
```

```python
>> rectangle.load(ConfigFactory.parse_file('/path/to/config'))
{'width': 2, 'height': 3, 'color.r': 32, 'color.g': 64, 'color.b': 128}
```
