Изменяемость
Изменяемые и неизменяемые типы данных в Python традиционно являются причиной головной боли у начинающих разработчиков. Как следует из названия изменяемые объекты можно модифицировать, неизменяемые - постоянны. Заставим голову кружиться? Смотрим пример:
1
foo = ['hi']
2
print(foo)
3
# Вывод: ['hi']
4
5
bar = foo
6
bar += ['bye']
7
print(foo)
8
# Вывод: ['hi', 'bye']
Copied!
Что произошло? Мы этого не ожидали! Логично было бы увидеть:
1
foo = ['hi']
2
print(foo)
3
# Вывод: ['hi']
4
5
bar = foo
6
bar += ['bye']
7
8
print(foo)
9
# Ожидаемый вывод: ['hi']
10
# Вывод: ['hi', 'bye']
11
12
print(bar)
13
# Вывод: ['hi', 'bye']
Copied!
Это не баг, а изменяемые типы данных в действии. Каждый раз, когда вы присваиваете значение переменной изменяемого типа другой переменной, все изменения с этим значением будут отражаться на обоих переменных. Новая переменная становится ссылкой на старую. Так происходит только с изменяемыми типами данных. Вот пример с использованием функций и изменяемых типов данных:
1
def add_to(num, target=[]):
2
target.append(num)
3
return target
4
5
add_to(1)
6
# Вывод: [1]
7
8
add_to(2)
9
# Вывод: [1, 2]
10
11
add_to(3)
12
# Вывод: [1, 2, 3]
Copied!
Вы могли ожидать другого поведения. Например, что функция add_to будет возвращать новый список при каждом вызове:
1
def add_to(num, target=[]):
2
target.append(num)
3
return target
4
5
add_to(1)
6
# Вывод: [1]
7
8
add_to(2)
9
# Вывод: [2]
10
11
add_to(3)
12
# Вывод: [3]
Copied!
Причиной, опять же, является изменяемость списков, которая и вызывает основную боль. В Python аргументы функции обрабатываются при определении функции, а не при её вызове. По этой причине вы никогда не должны присваивать аргументам по умолчанию значения изменяемых типов, если абсолютно точно не уверены в своих действиях конечно. Правильным подходом будет такой код:
1
def add_to(element, target=None):
2
if target is None:
3
target = []
4
target.append(element)
5
return target
Copied!
Каждый раз при вызове функции без аргумента target будет создан новый список. К примеру:
1
add_to(42)
2
# Вывод: [42]
3
4
add_to(42)
5
# Вывод: [42]
6
7
add_to(42)
8
# Вывод: [42]
Copied!
Last modified 3yr ago
Copy link