# Изменяемость

Изменяемые и неизменяемые типы данных в Python традиционно являются причиной головной боли у начинающих разработчиков. Как следует из названия изменяемые объекты *можно модифицировать*, неизменяемые - *постоянны*. Заставим голову кружиться? Смотрим пример:

```python
foo = ['hi']
print(foo)
# Вывод: ['hi']

bar = foo
bar += ['bye']
print(foo)
# Вывод: ['hi', 'bye']
```

Что произошло? Мы этого не ожидали! Логично было бы увидеть:

```python
foo = ['hi']
print(foo)
# Вывод: ['hi']

bar = foo
bar += ['bye']

print(foo)
# Ожидаемый вывод: ['hi']
# Вывод: ['hi', 'bye']

print(bar)
# Вывод: ['hi', 'bye']
```

Это не баг, а изменяемые типы данных в действии. Каждый раз, когда вы присваиваете значение переменной изменяемого типа другой переменной, все изменения с этим значением будут отражаться на обоих переменных. Новая переменная становится ссылкой на старую. Так происходит только с изменяемыми типами данных. Вот пример с использованием функций и изменяемых типов данных:

```python
def add_to(num, target=[]):
    target.append(num)
    return target

add_to(1)
# Вывод: [1]

add_to(2)
# Вывод: [1, 2]

add_to(3)
# Вывод: [1, 2, 3]
```

Вы могли ожидать другого поведения. Например, что функция `add_to` будет возвращать новый список при каждом вызове:

```python
def add_to(num, target=[]):
    target.append(num)
    return target

add_to(1)
# Вывод: [1]

add_to(2)
# Вывод: [2]

add_to(3)
# Вывод: [3]
```

Причиной, опять же, является изменяемость списков, которая и вызывает основную боль. В Python аргументы функции обрабатываются при определении функции, а не при её вызове. По этой причине вы никогда не должны присваивать аргументам по умолчанию значения изменяемых типов, если абсолютно точно не уверены в своих действиях конечно. Правильным подходом будет такой код:

```python
def add_to(element, target=None):
    if target is None:
        target = []
    target.append(element)
    return target
```

Каждый раз при вызове функции без аргумента `target` будет создан новый список. К примеру:

```python
add_to(42)
# Вывод: [42]

add_to(42)
# Вывод: [42]

add_to(42)
# Вывод: [42]
```
