我对以下示例感到困惑:
def append(elem, to=None):
if to is None:
to = []
to.append(elem)
return to
append(5)
# Out: [5]
append(3) # A new list is created
# Out: [3]
这里的要点应该是你在每次函数调用开始时将“to”重置为空列表,以避免以下情况:
append(5)
# Out: [5]
append(3) # A new list is created
# Out: [5, 3]
但是你怎么能检查“to”是否将它设置为[]?在我看来,你要么拉入定义中定义的“to”,要么拉动上次调用修改的“to”。这是如何工作的?
答案 0 :(得分:2)
使用默认参数定义函数时,如果未提供该参数,则该函数将使用该参数的默认值。因此,对于append(5)
,未指定to
,因此函数假定to
的值为None
- 它实际上与调用append(5, None)
相同}。
现在,函数检查if to is None
,它是to
被重新分配给空列表。 5
会附加到列表中,并返回列表。
当您拨打第二个电话append(3)
时,再次呼叫append(3, None)
。同样,if to is None
评估为True
,to
被重新分配到空列表。然后,3
被附加到该空列表,并返回该列表。
由于默认参数(在本例中为None
)是不可变的,因此to
上的操作不会持续到函数调用的结束。该函数有自己的内存块,当函数返回时会被清除。
但是,如果默认参数是可变的(例如[]
),则在定义函数时创建该值(即当python看到def func(arg1, arg2=[])
时,它会在内存中创建一个空列表,每次调用此函数时都使用该列表)。因此,对该列表所做的任何更改都将持续到函数的结尾,因为当函数定义时(在函数称为之前)创建了可变默认参数
答案 1 :(得分:1)
我将在这里引用Common Gotchas — The Hitchhiker's Guide to Python:
例如:
def append_to(element, to=[]):
to.append(element)
return to
定义函数时会创建一个新列表,并且相同 列表用于每次连续调用。
Python的默认参数在函数时被计算一次 定义,而不是每次调用函数(就像它说的那样) 红宝石)。这意味着如果你使用一个可变的默认参数和 改变它,你将为所有未来的电话改变该对象 也是这个功能。
此外,如果您不想使用无蚂蚁,请将其视为antipattern,您可以使用更多更好的类型:
def append_to(element, to=list):
if callable(to):
to = to()
to.append(element)
return to
我不知道它是否更好