这很难。我想不仅动态创建方法,还想将装饰器与它们相关联。这就是我试过的
import inspect
import types
class Dynamo(object):
pass
def call_me_dec(func):
print 'I am here'
return func
def add_dynamo(cls,i):
# @call_me_dec
def innerdynamo(self):
print "in dynamo %d" % i
return i
innerdynamo.__doc__ = "docstring for dynamo%d" % i
innerdynamo.__name__ = "dynamo%d" % i
setattr(cls, innerdynamo.__name__, innerdynamo)
def add_decorators(cls):
for name, fn in inspect.getmembers(cls):
if isinstance(fn, types.UnboundMethodType):
setattr(cls, name, call_me_dec(fn))
for i in range(2):
add_dynamo(Dynamo, i)
add_decorators(Dynamo)
d=Dynamo()
d.dynamo0()
d.dynamo1()
输出结果为:
I am here
I am here
in dynamo 0
in dynamo 1
预期产出:
I am here
in dynamo 0
I am here
in dynamo 1
请解释为什么会发生这种情况,如何才能获得理想的结果?
答案 0 :(得分:5)
您看到的是因为装饰器代码是在创建装饰函数时调用的,而不是在调用函数时调用的。如果你想让代码在调用时运行,你需要让装饰器返回一个调用装饰方法的可调用(通常是一个闭包)。例如:
def call_me_dec(func):
print 'Decorating %s' % func
def func_wrapper(*args, **kwargs):
print 'Calling %s' % func
return func(*args, **kwargs)
return func_wrapper
装饰器语法只是语法糖。记住:
def func():
pass
func = deco(func)
相当于
@deco
def func():
pass
无论哪种方式,您最终都会在本地名称空间中使用func
标签,该标签引用从func
传递的deco
作为明确定义的deco
返回的对象。 Decorator语法捆绑了一些额外的检查(比如确保{{1}}之间的输入和输出始终是callables),但基本上,如果某些东西在示例1中以给定的方式工作,它将在示例2中以这种方式工作。