从以前的函数调用中保留的函数参数中的默认值



我注意到python中有一种奇怪的行为,谁能告诉我这种行为的原因?

如果我调用一个没有属性的函数,那么默认值是保留其状态。您可以查看以下示例以更好地理解

class EvenStream(object):
def __init__(self):
self.current = 0
def get_next(self):
to_return = self.current
self.current += 2
return to_return

class OddStream(object):
def __init__(self):
self.current = 1
def get_next(self):
to_return = self.current
self.current += 2
return to_return

def print_from_stream(n, stream=EvenStream()):
for _ in range(n):
print(stream.get_next())

print_from_stream(2)
print('*****')
print_from_stream(2)
print('*****')
print_from_stream(2, OddStream())
print('*****')
print_from_stream(2, OddStream())

输出: 我期待 0,2,0,2,但它给了我 0,2,4,6

0
2
*****
4
6
*****
1
3
*****
1
3

>发生了什么?

当蟒蛇看到

def print_from_stream(n, stream=EvenStream()):

它将EvenStream()评估为默认参数。这是一个确定的对象。每次使用默认参数调用print_from_stream时,它都会使用首次评估EvenStream()时创建的同一实例。print_from_stream现在有一个关联的对象default_stream。此对象永远不会使用新EvenStream更新。C++术语中,您已经创建了一个static变量。

修复

print_from_stream的默认参数设为类似于None。然后,添加

if stream is None:
stream = EvenStream()

到函数的顶部。每次使用默认参数调用函数时,这将对EvenStream()进行新的实例化。

请注意,它与以前略有不同,因为print_from_stream(10, None)现在可以工作并提供偶数,而不是崩溃。这在 Python 中仍然被认为是一种很好的做法,类似于在 JS 函数中传递undefined就像你没有给出任何参数一样。如果用户不想命名其参数,它允许用户跳过第二个参数以转到第三个参数。

最新更新