Python 3.5 装饰器和函数域
Python 3.5 Decorators and function fields
我有以下代码片段:
def wrapper(func):
def wrapped(*args, **kwargs):
func.var = 0
return func(*args, **kwargs)
return wrapped
@wrapper
def f_out():
print(f_out.var)
你能解释一下为什么 运行 f_out()
加薪吗:
AttributeError: 'function' object has no attribute 'var'
编辑
我必须详细说明,因为答案给了我替代方案,但这不适用于我想要的情况。给定以下代码段:
def wrapper(func):
def wrapped(*args, **kwargs):
func.var = 0
ret = func(*args, **kwargs)
print(func.var)
return wrapped
@wrapper
def f_out():
f_out.var = 1
f_out()
print(f_out.var)
我得到输出:
0
1
为什么会这样?
如果 return func
你必须添加 return wrapped
试试这个:
def wrapper(func):
def wrapped(*args, **kwargs):
func.var = 0
return func(*args, **kwargs)
return wrapped
@wrapper
def f_out():
print(f_out.var)
正确的方法是 return 包装函数并在 return 之前更改它:
def wrapper(func):
def wrapped(*args, **kwargs):
return func(*args, **kwargs)
wrapped.var = 0
return wrapped
@wrapper
def f_out():
print(f_out.var)
你正确地得到:
print(f_out())
给予
0
更新后的片段更改了 var
属性两次:
- 第一次在包装器中将原始函数的属性设置为 0 并在调用原始函数后打印它
- 然后当从包装器调用原始函数时,它会将引用为
f_out
的函数的属性 设置为 1。但在那一刻,函数引用为 f_out
的是包装函数,不再是原始函数。
因此,当您稍后打印 f_out.var
时,您会打印包装函数的属性 1。
这里是一个稍微修改过的代码来演示它:
def wrapper(func):
def wrapped(*args, **kwargs):
wrapped.orig = func # keeps a ref to the original function
func.var = 0
ret = func(*args, **kwargs)
print(func.var)
return wrapped
@wrapper
def f_out():
f_out.var = 1
f_out()
print(f_out.var, f_out.orig.var)
它打印
0
1 0
Decorator 在您调用函数时包装您的函数。
因此,当您调用 f_out()
时,它会 returns 1
。它是您调用的包装函数,而不是它的定义。
@wrapper
def f_out()
等于
wrapper(f_out)
当你调用它时。
当您尝试打印 f_out.var
时,它 returns 来自函数定义的值。
我有以下代码片段:
def wrapper(func):
def wrapped(*args, **kwargs):
func.var = 0
return func(*args, **kwargs)
return wrapped
@wrapper
def f_out():
print(f_out.var)
你能解释一下为什么 运行 f_out()
加薪吗:
AttributeError: 'function' object has no attribute 'var'
编辑
我必须详细说明,因为答案给了我替代方案,但这不适用于我想要的情况。给定以下代码段:
def wrapper(func):
def wrapped(*args, **kwargs):
func.var = 0
ret = func(*args, **kwargs)
print(func.var)
return wrapped
@wrapper
def f_out():
f_out.var = 1
f_out()
print(f_out.var)
我得到输出:
0
1
为什么会这样?
如果 return func
你必须添加 return wrapped
试试这个:
def wrapper(func):
def wrapped(*args, **kwargs):
func.var = 0
return func(*args, **kwargs)
return wrapped
@wrapper
def f_out():
print(f_out.var)
正确的方法是 return 包装函数并在 return 之前更改它:
def wrapper(func):
def wrapped(*args, **kwargs):
return func(*args, **kwargs)
wrapped.var = 0
return wrapped
@wrapper
def f_out():
print(f_out.var)
你正确地得到:
print(f_out())
给予
0
更新后的片段更改了 var
属性两次:
- 第一次在包装器中将原始函数的属性设置为 0 并在调用原始函数后打印它
- 然后当从包装器调用原始函数时,它会将引用为
f_out
的函数的属性 设置为 1。但在那一刻,函数引用为f_out
的是包装函数,不再是原始函数。
因此,当您稍后打印 f_out.var
时,您会打印包装函数的属性 1。
这里是一个稍微修改过的代码来演示它:
def wrapper(func):
def wrapped(*args, **kwargs):
wrapped.orig = func # keeps a ref to the original function
func.var = 0
ret = func(*args, **kwargs)
print(func.var)
return wrapped
@wrapper
def f_out():
f_out.var = 1
f_out()
print(f_out.var, f_out.orig.var)
它打印
0
1 0
Decorator 在您调用函数时包装您的函数。
因此,当您调用 f_out()
时,它会 returns 1
。它是您调用的包装函数,而不是它的定义。
@wrapper
def f_out()
等于
wrapper(f_out)
当你调用它时。
当您尝试打印 f_out.var
时,它 returns 来自函数定义的值。