可变默认属性重置有人能指导我通过这个逻辑吗?

2024-04-18 12:15:48 发布

您现在位置: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”是否为None以将其设置为[]?在我看来,你要么拉入定义中定义的“to”,要么拉入上次调用修改的“to”。这是怎么回事?你知道吗


Tags: tonone重点newreturnif定义is
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=[])时,它会在内存中创建一个空列表,并在每次调用该函数时使用该列表)。因此,对该列表所做的任何更改都将保留到函数末尾,因为该可变默认参数是在定义函数时创建的(在调用函数之前)。你知道吗

我在这里引用Common Gotchas — The Hitchhiker's Guide to Python

例如:

def append_to(element, to=[]):
    to.append(element)
    return to

A new list is created once when the function is defined, and the same list is used in each successive call.

Python’s default arguments are evaluated once when the function is defined, not each time the function is called (like it is in say, Ruby). This means that if you use a mutable default argument and mutate it, you will and have mutated that object for all future calls to the function as well.

另外,如果您不喜欢使用none ant,请将其视为antipattern,您可以使用更高级的:

def append_to(element, to=list):
    if callable(to):
        to = to()
    to.append(element)
    return to

我不知道是不是更好

相关问题 更多 >