简体   繁体   English

带有@ syntax的python decorator参数

[英]python decorator arguments with @ syntax

I'm trying to use a cached property decorator that can take arguments. 我正在尝试使用可以接受参数的缓存属性装饰器。

I looked at this implementation: http://www.daniweb.com/software-development/python/code/217241/a-cached-property-decorator 我看了一下这个实现: 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 )

But the problem I have is that I cannot call the decorator with the @ syntax if I want to use the parameter: 但我遇到的问题是,如果我想使用参数,我不能使用@语法调用装饰器:

@cachedProperty(name='test') # This does NOT work
def my_func(self):
    return 'ok'

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

How to use the @ syntax with decorators arguments? 如何在装饰器参数中使用@语法?

Thanks 谢谢

You need a decorator factory , another wrapper that produces the 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

Use this as: 用它作为:

@cachedProperty(name='test')
def my_func(self):
    return 'ok'

A decorator is really just syntactic sugar for: 装饰者真的只是语法糖:

def my_func(self):
    return 'ok'
my_func = cachedProperty(name='test')(my_func)

so as long as the expression after @ returns your decorator [*] it doesn't matter what the expression itself actually does. 所以只要@之后的表达式返回你的装饰器[*] ,表达式本身实际上做什么并不重要。

In the above example, the @cachedProperty(name='test') part first executes cachedProperty(name='test') , and the return value of that call is used as the decorator. 在上面的示例中, @cachedProperty(name='test')部分首先执行cachedProperty(name='test') ,并将该调用的返回值用作装饰器。 In the above example, decorator is returned, so the my_func function is decorated by calling decorator(my_func) , and the return value of that call is property object, so that is what'll replace my_func . 在上面的例子中,返回了decorator ,因此通过调用decorator(my_func) my_func函数,并且该调用的返回值是property对象,因此这将替换my_func


[*] The @ expression syntax is deliberately limited in how much it is allowed to do. [*] @表达式语法故意限制允许执行的程度。 You can do attribute lookups and calls, that's it, the decorator grammar rule only allows an optional call with arguments at the end of a dotted name (where dots are optional): 你可以进行属性查找和调用,就是这样, decorator语法规则只允许在点名称末尾带有参数的可选调用(其中点是可选的):

 decorator ::= "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE) 

This is a deliberate limitation of the syntax. 这是对语法的故意限制

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM