你能在类中创建一个装饰器来查看类方法和变量吗?
装饰者在这里看不到:self.longcondition()
class Foo:
def __init__(self, name):
self.name = name
# decorator that will see the self.longcondition ???
class canRun(object):
def __init__(self, f):
self.f = f
def __call__(self, *args):
if self.longcondition(): # <-------- ???
self.f(*args)
# this is supposed to be a very long condition :)
def longcondition(self):
return isinstance(self.name, str)
@canRun # <------
def run(self, times):
for i in xrange(times):
print "%s. run... %s" % (i, self.name)
答案 0 :(得分:5)
没有必要将这个装饰器作为一个类来实现,并且不需要在Foo
类的定义中实现它。以下就足够了:
def canRun(meth):
def decorated_meth(self, *args, **kwargs):
if self.longcondition():
print 'Can run'
return meth(self, *args, **kwargs)
else:
print 'Cannot run'
return None
return decorated_meth
使用该装饰器似乎有效:
>>> Foo('hello').run(5)
Can run
0. run... hello
1. run... hello
2. run... hello
3. run... hello
4. run... hello
>>> Foo(123).run(5)
Cannot run
答案 1 :(得分:1)
我之前的回答是匆忙做出的。如果您想要编写装饰器,则应该使用wraps
模块中的functools
。它会为你解决困难。
定义canRun装饰器的正确方法是:
from functools import wraps
def canRun(f):
@wraps(f)
def wrapper(instance, *args):
if instance.longcondition():
return f(instance, *args)
return wrapper
canRun函数应该在类之外定义。
答案 2 :(得分:1)
你可以让它成为一个类,但你需要使用描述符协议
import types
class canRun(object):
def __init__(self, f):
self.f = f
self.o = object # <-- What the hell is this about?
def __call__(self, *args):
if self.longcondition():
self.f(*args)
def __get__(self, instance, owner):
return types.MethodType(self, instance)
当您想使用__call__
方法使用类实例修饰类方法时,总是需要使用描述符。这样做的原因是只传递了一个self
,它引用了装饰类的实例,而不是装饰方法的实例。