2014-01-20 17 views
0

继答案从this previous question约默认memoizing所有的类的方法,我使用这个元类:应用一个装饰的属性的getter

from inspect import isfunction 

class Immutable(type): 
    def __new__(cls, name, bases, dct): 
     for key, val in dct.items(): 
      # Look only at methods/functions; ignore those with 
      # "special" names (starting with an underscore) 
      if isfunction(val) and val.__name__[0] != '_': 
       dct[key] = memoized(val) 
      elif hasattr(val, 'fget'): 
       # It's a property; we currently can't memoize these 
       pass 
     return type.__new__(cls, name, bases, dct) 

此元类具有应用装饰memoized到的效果班级中的所有功能和方法。唯一的问题是它不适用于属性。 (使用此元类的类都被视为不可变的,所以我只担心只读属性在这里。)如果我尝试做一些像

from time import sleep 

class Foo(object): 
    __metaclass__ = Immutable 

    @property 
    def slow_calculation(self): 
     sleep(5) # simulate an intensive calculation 
     return 4 

然后slow_calculation不memoized,有一个五秒钟的延迟每次它被叫,不只是第一次。

问题是property()返回一个property对象,而不是一个函数,因此元类__new__中的isfunction测试不会捕获属性。正如你所看到的,我添加了一个可以找到属性的测试,但是我不知道如何将memoized装饰器应用到属性获取器fget。我想也许我可以说

elif hasattr(val, 'fget'): 
    val.fget = memoized(val.fget) 
    dct[key] = val 

但在这种情况下,我得到

Traceback (most recent call last): 
    [...] 
    File "utils.py", line 54, in __new__ 
    val.fget = memoized(val.fget) 
TypeError: Error when calling the metaclass bases 
    readonly attribute 

是否有一个装饰应用到属性的getter一些其他的方式?

回答

2
prop = property(memoized(prop.fget), prop.fset, prop.fdel, prop.__doc__) 

请勿修改属性;做一个新的。

+0

这样做。谢谢! – bdesham