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

arg*_*rgo 1 python python-3.x

我注意到 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())
Run Code Online (Sandbox Code Playgroud)

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

0
2
*****
4
6
*****
1
3
*****
1
3
Run Code Online (Sandbox Code Playgroud)

Nic*_*one 6

发生了什么?

当蟒蛇看到

def print_from_stream(n, stream=EvenStream()):
Run Code Online (Sandbox Code Playgroud)

EvenStream()作为默认参数进行计算。这是一个明确的对象。每次使用默认参数调用时,它都会使用首次评估print_from_stream时创建的同一实例。现在有一个关联的对象。该对象永远不会用新的. 用 C++ 术语来说,您已经创建了一个变量。EvenStream()print_from_streamdefault_streamEvenStreamstatic

修复方法

将默认参数设置为print_from_stream类似None. 然后加

if stream is None:
    stream = EvenStream()
Run Code Online (Sandbox Code Playgroud)

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

请注意,它与以前略有不同,因为print_from_stream(10, None)现在可以工作并提供偶数,而不是崩溃。这在 Python 中仍然被视为良好实践,类似于传入undefinedJS 函数与不提供任何参数的情况相同。如果用户不想命名他们的参数,它可以让用户跳过第二个参数也到达第三个参数。