Я отредактировал этот ответ, чтобы включить мысли из множества комментариев, опубликованных в вопросе.
Пример, который вы приводите: некорректен . Он изменяет список, который вы передаете, как побочный эффект. Если вы хотели, чтобы функция работала, не имеет смысла иметь аргумент по умолчанию. Также не имеет смысла возвращать обновленный список. Без аргумента по умолчанию проблема исчезнет.
Если вы намеревались вернуть новый список, вам нужно сделать копию списка ввода. Python предпочитает, чтобы все было ясно, поэтому вы должны сделать копию.
def better_append(new_item, a_list=[]):
new_list = list(a_list)
new_list.append(new_item)
return new_list
Для чего-то немного другого, вы можете сделать генератор, который может принимать список или генератор в качестве входных данных:
def generator_append(new_item, a_list=[]):
for x in a_list:
yield x
yield new_item
Я думаю, вы ошибочно полагаете, что Python по-разному обрабатывает изменяемые и неизменяемые аргументы по умолчанию; это просто неправда. Скорее неизменность аргумента заставляет вас незаметно изменить код, чтобы автоматически делать правильные вещи. Возьмите пример и примените его к строке, а не к списку:
def string_append(new_item, a_string=''):
a_string = a_string + new_item
return a_string
Этот код не изменяет переданную строку - он не может этого сделать, потому что строки неизменяемы. Он создает новую строку и назначает a_string для этой новой строки. Аргумент по умолчанию можно использовать снова и снова, потому что он не меняется, вы сделали его копию в начале.