【发布时间】:2011-06-22 20:41:48
【问题描述】:
我想使用装饰器包装除__init__ 之外的各种对象的所有方法。
class MyObject(object):
def method(self):
print "method called on %s" % str(self)
@property
def result(self):
return "Some derived property"
def my_decorator(func):
def _wrapped(*args, **kwargs):
print "Calling decorated function %s" % func
return func(*args, **kwargs)
return _wrapped
class WrappedObject(object):
def __init__(self, cls):
for attr, item in cls.__dict__.items():
if attr != '__init__' and (callable(item) or isinstance(item, property)):
setattr(cls, attr, my_decorator(item))
self._cls = cls
def __call__(self, *args, **kwargs):
return self._cls(*args, **kwargs)
inst = WrappedObject(MyObject)()
然而,一个属性实例结果的包装等价于:
@my_decorator
@property
def result(self):
return "Some derived property"
当期望的结果与此等价时:
@property
@my_decorator
def result(self):
return "Some derived property"
似乎属性对象的属性是只读的,防止在属性包装后修改函数。我已经对所需的hackery 级别不太满意,无论如何我都不想深入研究属性对象。
我能看到的唯一其他解决方案是动态生成一个我希望避免的元类。我错过了什么明显的东西吗?
【问题讨论】:
-
你有没有察觉到,在这段代码中,当你运行 WrapedObject 的 init 后,一旦它修改了原始类,你就不再有它的非包装版本了吗?跨度>
标签: python metaclass decorator