python中变量的生存期

2024-09-30 05:30:03 发布

您现在位置:Python中文网/ 问答频道 /正文

Possible Duplicate:
“Least Astonishment” in Python: The Mutable Default Argument

考虑以下两个函数

def a(var=[0]):
    print (var)
    var = var + [4]

def b(var=[0]):
    print (var)
    var.append(4)

它们的行为应该相同,但更重要的是,如果调用时没有参数,则两者都应该简单地打印“[0]”。行为完全不同,只有a()会一直打印'[0]'。在

^{pr2}$

为什么a()函数与b()函数不同?在

如果希望在函数没有参数通过的情况下用默认值覆盖变量,那么似乎不能使用list API。如果你这样做的话,函数会“记住”变量之前是什么。在

我的代码中的情况出现在递归函数中,所以仅仅“删除”不需要的变量并不能真正起作用。有没有办法在每次不带参数的情况下调用函数时重写一个变量?

经过数小时的研究,我发现了这一点。它可能与上述问题有关,并可能导致答案。我们可以这样定义生命周期类:

class lifetime:   # adapted from http://naml.us/blog/tag/variable-lifetime
    def __init__(self, name):
        self.name = name
        print ('creating: ' + name)
    def __del__(self):
        print ('destroying: ' + self.name)
    def __iadd__(self, a):
        self.append(a)
    def append(self, a):
        self.name += ' and ' + a.name
        print('appending: ' + a.name + ' to ' + self.name)

然后定义2个函数:

def a(var=lifetime('a')):
    print (var)
    var += life('appendage')

def b(var=lifetime('b')):
    print (var)
    var.append(life('appendage'))

>>> a()
<__main__.lifetime object at 0x00000000031FFA90>
creating: appendage
appending: appendage to a and appendage
destroying: appendage
>>> a()
<__main__.lifetime object at 0x00000000031FFA90>
creating: appendage
appending: appendage to a and appendage and appendage
destroying: appendage
>>> b()
<__main__.lifetime object at 0x00000000031FFB38>
creating: appendage
appending: appendage to b and appendage
destroying: appendage
>>> b()
<__main__.lifetime object at 0x00000000031FFB38>
creating: appendage
appending: appendage to b and appendage and appendage
destroying: appendage

它似乎只对参数的默认值求值一次,然后使用该值的任何值。它从不说“创造:a”或“创造:b”。所以,如果每次都计算默认参数,可能会得到实际问题的答案。在


Tags: andto函数nameselfcreating参数var
3条回答

正如您所说,当函数被声明时,这些默认值只计算一次。这就是为什么将列表或散列文本指定为默认值从来都不是一个好主意,因为对于所有函数调用,您只能得到一个实例。在

这个问题被描述为here。在

这两个函数的行为不同,因为在第一个函数中,您将局部变量var重新定义为[0] + [4](不是附加到用[0]初始化的原始列表中),而在第二个函数中,您实际上是附加到原始初始化列表中,将其从[0]转换为[0, 4]。正如你提到的-默认值只评估一次。在

因为这两个代码片段做了两件本质上不同的事情。var + [4]创建一个由var列表的内容组成的新列表,并添加{},然后将这个新列表分配给varvar.append(4)另一方面,将数字4追加到现有列表中。在

您的问题是var=[0]只计算一次,然后重用,因为您的append更改了变量本身,您将看到对以后调用的影响。另一个代码只向局部变量分配一个新对象,这在以后不会有效果。在

通常不使用可修改的默认值,而是写下:

def foo(var=None):
    if var is None: var = [0]

如果需要记住以前调用的数据,请将整个函数放入一个类中。在

相关问题 更多 >

    热门问题