考虑以下两个函数
def a(var=[0]):
print (var)
var = var + [4]
def b(var=[0]):
print (var)
var.append(4)
它们的行为应该相同,但更重要的是,如果不带参数调用,两者都应该简单地打印“[0]”。行为非常不同,只有 a() 会一直打印 '[0]'。
>>> a()
[0]
>>> a()
[0]
>>> a()
[0]
>>> b()
[0]
>>> b()
[0, 4]
>>> b()
[0, 4, 4]
为什么 a() 与 b() 的功能不同?
如果您希望在没有参数传递给函数的情况下使用默认值覆盖变量,那么您似乎无法使用列表 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”。所以也许如果每次都评估默认参数,它会导致对实际问题的回答。