如何冻结可变的默认参数值?
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]
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]