可变的默认属性重置 - 有人可以指导我完成这个逻辑吗?

时间:2016-07-26 02:46:20

标签: python

我对以下示例感到困惑:

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”。这是如何工作的?

2 个答案:

答案 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评估为Trueto被重新分配到空列表。然后,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

我不知道它是否更好