Python: список по умолчанию в функции

Из программирования Саммерфилда на Python3:

в нем говорится следующее: когда заданы значения по умолчанию, они создаются во время выполнения оператора def, а не при вызове функции. Но мой вопрос для следующего примера:

def append_if_even(x, lst =None):
    lst = [] if lst is None else lst
    if x % 2 ==0:
        lst.append(x)
    return lst

При первом выполнении определения времени lst указывает на None. Но после вызова функции append_if_even(2)

  • Не должен ли lst указывать на [2], так как после lst.append(x) lst больше не указывает на None?

  • Почему при следующем выполнении lst не указывает ни на что?

  • Что на самом деле происходит внутри этого вызова функции append_if_even(2)?

person will Liu    schedule 06.04.2017    source источник
comment
параметры x и lst не являются глобальными. Таким образом, их установка не влияет на второй вызов.   -  person Willem Van Onsem    schedule 06.04.2017
comment
заключается в том, что после создания функции создается пространство памяти для аргумента этой функции по умолчанию. Когда требуется аргумент по умолчанию, этот локальный список будет назначен созданному пространству со значением None ? Так работает аргумент по умолчанию в python?   -  person will Liu    schedule 06.04.2017
comment
@wllLiu: есть только один None. Но скажем, вы указали lst = []. Он создаст один список. Если вы не укажете lst, lst будет ссылаться на этот список. В противном случае к данному аргументу. Но установка самого параметра не имеет значения.   -  person Willem Van Onsem    schedule 06.04.2017


Ответы (1)


Не должен ли lst указывать на [2], так как после lst.append(x) lst больше не указывает на None? Почему при следующем выполнении lst не указывает ни на что?

Это именно то, что вы предотвращаете, используя конструкцию lst=None, lst = [] if lst is None else lst. Хотя аргументы функции по умолчанию оцениваются только один раз во время компиляции, код внутри функции оценивается каждый раз, когда функция выполняется. Таким образом, каждый раз, когда вы выполняете функцию без передачи значения для lst, она начинается со значения по умолчанию None, а затем сразу же заменяется новым пустым списком при выполнении первой строки функции.

Если бы вы вместо этого определили функцию следующим образом:

def append_if_even(x, lst=[]):
    if x % 2 ==0:
        lst.append(x)
    return lst

Тогда он будет действовать так, как вы описываете. Значением по умолчанию для lst будет один и тот же список (изначально пустой) для каждого запуска функции, и каждое четное число, переданное функции, будет добавлено в один растущий список.

Дополнительные сведения см. в разделе "Least Astonishment" и "Изменяемый аргумент по умолчанию". .

person glibdud    schedule 06.04.2017