48. Что выведет код с изменяемым аргументом по умолчанию
Условие задачи:
Дана функция с аргументом по умолчанию в виде списка. Нужно определить, что выведет программа при последовательных вызовах этой функции, и объяснить причину такого поведения.
def extendList(val, list=[]):
list.append(val)
return list
list1 = extendList(10)
list2 = extendList(123, [])
list3 = extendList('a')
print ""list1 = %s"" % list1
print ""list2 = %s"" % list2
print ""list3 = %s"" % list3
Спойлеры к решению
Подсказки
- Аргумент по умолчанию
list=[]создаётся один раз в момент определения функции. - Если функцию вызвать без второго аргумента, будет использоваться один и тот же список.
list1иlist3используют общий список по умолчанию.list2использует отдельный список, потому что он передан явно:[].- Не стоит называть параметр
list, потому что так перекрывается встроенный типlist.
Решение
Исходная идея кода:
def extendList(val, list=[]):
list.append(val)
return list
list1 = extendList(10)
list2 = extendList(123, [])
list3 = extendList("a")
print("list1 = %s" % list1)
print("list2 = %s" % list2)
print("list3 = %s" % list3)
Результат:
list1 = [10, 'a']
list2 = [123]
list3 = [10, 'a']
Разбор:
list1 = extendList(10)
Функция вызывается без второго аргумента, поэтому используется список по умолчанию. После добавления 10 он становится таким:
[10]
Дальше:
list2 = extendList(123, [])
Здесь вторым аргументом явно передан новый пустой список. Поэтому 123 добавляется не в общий список по умолчанию, а в отдельный список:
[123]
Дальше:
list3 = extendList("a")
Функция снова вызывается без второго аргумента, поэтому снова используется тот же самый список по умолчанию, в котором уже лежит 10. После добавления "a" он становится таким:
[10, "a"]
Так как list1 и list3 ссылаются на один и тот же список, при выводе оба будут равны:
[10, "a"]
Правильная реализация без изменяемого аргумента по умолчанию:
def extend_list(val, items=None):
if items is None:
items = []
items.append(val)
return items
В таком варианте новый список создаётся при каждом вызове функции без второго аргумента, поэтому данные между вызовами не будут случайно накапливаться.