我有一个工作装饰器,可以在一段时间内运行一个方法 True 并且它在常规函数上运行良好。当我尝试装饰实例的函数时出现问题。
这是装饰器:
from threading import Thread
def run_in_while_true(f):
def decorator(break_condition=False):
def wrapper(*args, **kwargs):
while True:
if break_condition:
return
f(*args, **kwargs)
return wrapper
return decorator
class A(object):
@run_in_while_true
def print_ch(self, ch):
print ch
@run_in_while_true
def print_with_dec(ch):
print ch
print_with_dec()('f') # Call 1
# If i would want to pass a break condition i would write this
print_with_dec(1==1 and 2*2==4)('f')
a = A()
a.print_ch()('4') # Call 2
`
调用 1 按预期运行并打印大量 f。 由于某种原因,调用 2 获取了 self 参数,其中break_condition 是,并且因为检查break_condition 为true 并且函数返回。
我需要以什么方式更 retrofit 饰器才能使其也适用于对象?提前致谢
最佳答案
你生成的代码看起来真的很奇怪:
a.print_ch()('4') # Call 2
这是因为你的装饰器中有一个额外的层:
def run_in_while_true(f):
def decorator(break_condition=False):
def wrapper(*args, **kwargs):
@run_in_while_true
装饰器将返回 decorator
,必须调用它才能返回 wrapper
,必须调用它来评估一个结果。 @run_in_while_true
作为装饰的一部分被自动调用。另外两个需要两组括号,如代码中所示。
这是一个问题,因为方法调用(例如 a.print_ch()
)会自动将调用者传递给第一次调用:
a.print_ch()('4')
# is much the same as
# A.print_ch(self=a)('4')
这解释了为什么您的调用者会处于 break_condition 状态。
我建议你尝试统一两个内部函数。只需将诸如 break_condition
或 break_when
或 break_if
之类的命名参数传递给函数/方法,并让包装器拦截该值:
导入函数工具
def run_until_done(func):
@functools.wraps
def wrapper(*args, break_if=None, **kwargs):
done = break_if if callable(break_if) else lambda: break_if
while not done():
func(*args, **kwargs)
return wrapper
@run_until_done
def print_with_dec(ch):
print ch
print_with_dec('4', break_if=lambda: 1==1 and is_done())
关于python - 我的装饰器适用于常规功能,但不适用于实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54587513/