2 回答

TA貢獻(xiàn)2036條經(jīng)驗 獲得超8個贊
您生成的代碼看起來很奇怪:
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,其中有被稱為評估結(jié)果。該@run_in_while_true作為裝飾的一部分被自動調(diào)用。另外兩個需要兩組括號,如您的代碼所示。
這是一個問題,因為方法調(diào)用,如a.print_ch(),會自動將調(diào)用者傳遞給第一次調(diào)用:
a.print_ch()('4')
# is much the same as
# A.print_ch(self=a)('4')
這解釋了為什么你在你的 break_condition.
我建議您嘗試統(tǒng)一兩個內(nèi)部功能。只需將命名參數(shù)(如break_condition或break_when或)break_if傳遞給函數(shù)/方法,并讓包裝器攔截該值:import functools
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())

TA貢獻(xiàn)1828條經(jīng)驗 獲得超4個贊
感謝大家的幫助,在研究了更多關(guān)于從對象調(diào)用函數(shù)的方式之后,我編寫了這些最終的裝飾器。它們都適用于對象的常規(guī)函數(shù)和方法。一個在循環(huán)中運行函數(shù)直到滿足條件,另一個在線程中運行第一個函數(shù),因此程序不會等待。
裝飾者
def loop_in_while_oop(f):
""" Runs a function in a loop, params have to be passed by name"""
def decorated(self=None, break_if=None, *args,**kwargs):
"""
:param self: Will be passed automatically if needed
:param break_if: Lambada expression for when to stop running the while loop
"""
done = break_if if callable(break_if) else lambda: break_if
while not done():
if self is not None:
f(self, *args, **kwargs)
else:
f(*args, **kwargs)
return decorated
def loop_in_thread_oop(f):
""" Runs function in a loop in a thread, MUST: pass arguments by name"""
def decorated(self=None, break_if=lambda: False, *args, **kwargs):
"""
:param self: Will be passed automatically if needed
:param break_if: Lambada expression for when to stop running the while loop, if value not passed will run forever
"""
f1 = loop_in_while_oop(f)
t = Thread(target=f1, args=args, kwargs=dict(self=self, break_if=break_if, **kwargs))
t.start()
return decorated
使用裝飾器
class SomeObj(object):
@loop_in_thread_oop
def print_c(self, c):
print c
@loop_in_thread_oop
def p1(f):
print f
@loop_in_thread_oop
def p2(f):
print f
if __name__ == '__main__':
a = SomeObj()
start = time.time()
a.print_c(c='a') # Will run forever because break_if was not specified
p1(f='3', break_if=lambda: time.time() - start > 3) # Will stop after 3 seconds
p2(f='5', break_if=lambda: time.time() - start > 5) # Will stop after 5 seconds
輸出:
0-3 秒之間:打印a35(順序不固定)
3-5 秒之間:打印a5(順序不固定)
3-5 秒之間:打印a
添加回答
舉報