66 Изменяемый аргумент по умолчанию

 def foo(li=[]):
    li.append(1)
    print(li)

foo([2])
# Out: [2, 1]
foo([3])
# Out: [3, 1]

 

Этот код ведет себя как ожидалось, но что если мы не передадим аргумент?

 foo()
# Out: [1] As expected...

foo()
# Out: [1, 1]  Not as expected...

 

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

Чтобы обойти это, используйте только неизменяемые типы для аргументов по умолчанию:

 def foo(li=None):
    if not li:
        li = []
    li.append(1)
    print(li)

foo()
# Out: [1]

foo()
# Out: [1]

 

В то время как улучшение , и , хотя , if not li правильно оценивает в False , многие другие объекты , а также, такие как последовательности нулевой длины. Следующие примеры аргументов могут привести к непредвиденным результатам:

 x = []
foo(li=x)
# Out: [1]

foo(li="")
# Out: [1]

foo(li=0) 
# Out: [1]

 

Идиоматический подход непосредственно проверить аргумент против None объекта:

 def foo(li=None):
    if li is None:
        li = []
    li.append(1)
    print(li)

foo()
# Out: [1]