我正在尝试使用一个可以接受参数的缓存属性修饰器。
我看过这个实现:http://www.daniweb.com/software-development/python/code/217241/a-cached-property-decorator

from functools import update_wrapper

def cachedProperty (func ,name =None ):
  if name is None :
    name =func .__name__
  def _get (self ):
    try :
      return self .__dict__ [name ]
    except KeyError :
      value =func (self )
      self .__dict__ [name ]=value
      return value
  update_wrapper (_get ,func )
  def _del (self ):
    self .__dict__ .pop (name ,None )
  return property (_get ,None ,_del )

但问题是,如果我想使用参数,就不能用@syntax调用decorator:
@cachedProperty(name='test') # This does NOT work
def my_func(self):
    return 'ok'

# Only this way works
cachedProperty(my_func, name='test')

如何将@syntax与decorators参数一起使用?
谢谢

最佳答案

您需要一个decorator工厂,另一个产生decorator的包装器:

from functools import wraps

def cachedProperty(name=None):
    def decorator(func):
        if decorator.name is None:
            decorator.name = func.__name__
        @wraps(func)
        def _get(self):
            try:
                return self.__dict__[decorator.name]
            except KeyError:
                value = func(self)
            self.__dict__[decorator.name] = value
            return value
        def _del(self):
            self.__dict__.pop(decorator.name, None)
        return property(_get, None, _del)
    decorator.name = name
    return decorator

将其用作:
@cachedProperty(name='test')
def my_func(self):
    return 'ok'

装饰师实际上只是对以下内容的语法甜头:
def my_func(self):
    return 'ok'
my_func = cachedProperty(name='test')(my_func)

因此,只要@后面的表达式返回decorator[*],那么表达式本身实际做什么并不重要。
在上面的示例中,@cachedProperty(name='test')部分首先执行cachedProperty(name='test'),该调用的返回值用作修饰器。在上面的例子中,decorator是返回的,所以my_func函数是通过调用decorator(my_func)来修饰的,并且该调用的返回值是property对象,所以这就是将要替换的对象。
[*]表达式语法被故意限制在允许的范围内。您可以进行属性查找和调用,也就是说,my_func grammar rule只允许在点状名称末尾带有参数的可选调用(其中点是可选的):
decorator               ::=  "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE)

这是一个deliberate limitation的语法。

关于python - 带有@ syntax的python decorator参数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22271923/

10-12 16:41