我有一个工作的装饰器,可以在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按预期运行,并且打印很多。 出于某种原因,调用2会获得self参数,其中break_condition为break,并且因为break_condition的检查为true并返回函数。
我需要以哪种方式更改装饰器,使其也可以与对象一起使用?预先感谢
答案 0 :(得分:0)
您得到的代码看起来真的很奇怪:
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()
作为装饰的一部分被自动调用。如代码中所示,另外两个需要两套paren。
这是一个问题,因为方法调用(如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())
之类的命名参数传递给函数/方法,并让包装器截获该值:
导入功能工具
Approach 1
public sealed class Singleton {
//Private ctor of course :P
private Singleton() {}
// Instance property to access Singleton Instance
public static Singleton Instance { get { return Nested.instance; } }
private class Nested {
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Nested() { }
internal static readonly Singleton instance = new Singleton();
}
}
Approach 2
public sealed class Singleton
{
private static readonly Lazy<Singleton> lazy =
new Lazy<Singleton>(() => new Singleton());
public static Singleton Instance { get { return lazy.Value; } }
private Singleton()
{
}
}
答案 1 :(得分:0)
感谢大家的帮助,在深入研究了从对象调用函数的方式之后,我编写了这些最终修饰符。它们都适用于常规功能和对象方法。一个循环运行该函数直到满足条件为止,另一个循环在线程中运行第一个函数,因此程序无需等待。
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
输出:
a35
(顺序不是恒定的)a5
(顺序不是恒定的)a