如何冻结可变的默认参数值?

How to freeze mutable default parameter values?

Python 选择遵循只评估函数签名一次的设计决策。所以这段代码:

def test(x=[]):
    x.append(5)
    return x

print(test())
print(test())

打印:

[5]

[5, 5]

我知道可以使用 None 作为默认值,如果是 None.

则可以在函数内部更改参数值

我如何编写一些代码来改变test的行为,使默认参数在我每次调用该函数时都会重新计算?该解决方案可以包括装饰器并使用 类 作为默认值。

我们可以使用函数的 __default__ 属性 到 "freeze" 默认值(以及 __kwargs__ 到 "freeze" 默认关键字参数):

def freeze_defaults(func):
     defaults = func.__defaults__
     kwdefaults = func.__kwdefaults__
     @functools.wraps(func) 
     def wrapper(*args, **kwargs): 
         func.__defaults__ = copy.deepcopy(defaults) 
         func.__kwdefaults__ = copy.deepcopy(kwdefaults)
         return func(*args, **kwargs) 
     return wrapper

现在:

@freeze_defaults
def test(x=[]):
    x.append(5)
    return x

print(test())
print(test())

打印:

[5]

[5]

甚至:

@freeze_defaults
def test(x=['hello!']):
    x.append(5)
    return x

print(test())
print(test())

打印:

['hello!', 5]

['hello!', 5]