使用@语法的python装饰器参数 [英] python decorator arguments with @ syntax

查看:75
本文介绍了使用@语法的python装饰器参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用可以接受参数的缓存属性装饰器。

I'm trying to use a cached property decorator that can take arguments.

我查看了以下实现: http://www.daniweb.com/software-development/python/code/217241/a-缓存的属性装饰器

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 )

但是我遇到的问题是,如果我想使用参数,则无法使用@语法调用装饰器r:

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?

谢谢

推荐答案

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

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

将此用作:

@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.

在上面的示例中, @cachedProperty(name ='test')部分首先执行 cachedProperty(name ='test '),并且该调用的返回值用作修饰符。在上面的示例中,返回了 decorator ,因此通过调用 decorator装饰 my_func 函数。 (my_func),并且该调用的返回值是属性对象,因此将替换 my_func

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. 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 语法规则仅允许在点分名称(其中点是可选的)末尾带有参数的可选调用:

[*] 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               ::=  "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE)


这是故意的语法限制

这篇关于使用@语法的python装饰器参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆