gpt4 book ai didi

python - 在 Python 的装饰器中重新分配参数

转载 作者:太空宇宙 更新时间:2023-11-03 15:31:26 25 4
gpt4 key购买 nike

考虑一个带参数的简单 Python 装饰器:

def decorator_factory(a=None):
def decorator(func):
def wrapper(*args, **kws):
return func(*args, **kws) + a
return wrapper
return decorator

有时,根据参数的实际值重新分配参数值很有用。这是 Python 中的一种常见设计模式,尤其是考虑到默认参数可变性的问题,但它可以用于其他情况,例如:

def foo(a, b=None):
if b is None:
b = a
return a + b

但是,使用装饰器模仿类似设计模式的类似代码,例如以下玩具代码:

def decorator_factory(a=None):
def decorator(func):
def wrapper(*args, **kws):
y = func(*args, **kws)
if a is None:
a = y
return y + a
return wrapper
return decorator

将引发以下问题:

UnboundLocalError: local variable 'a' referenced before assignment

如何解决?

最佳答案

这是一个范围界定问题。通过重新分配名称,Python 解释器会保留重新分配的名称供本地使用,从而从外部作用域中隐藏先前的值,如果在第一次分配之前使用该名称,则会导致名称未绑定(bind)。

对此最简单的解决方案是从不wrapper() 中重新分配装饰器参数的名称。只需在整个过程中使用不同的名称即可。

例如:

def decorator_factory(a=None):
def decorator(func):
def wrapper(*args, **kws):
y = func(*args, **kws)
a_ = y if a is None else a
return y + a_
return wrapper
return decorator


@decorator_factory()
def foo(x):
return 2 * x


print(foo(2))
# 8
print(foo(3))
# 12

注意:nonlocal 语句将避免引发 UnboundLocalError,但参数的值将在多个函数调用中保持不变,例如:

def decorator_factory(a=None):
def decorator(func):
def wrapper(*args, **kws):
nonlocal a
y = func(*args, **kws)
a = y if a is None else a
return y + a
return wrapper
return decorator


@decorator_factory()
def foo(x):
return 2 * x


print(foo(2))
# 8
print(foo(3))
# 10

最后一个 foo() 调用给出了 10,因为修饰函数中 a=4 的值来自之前的 foo() 调用。

关于python - 在 Python 的装饰器中重新分配参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57691284/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com