带有@syntax的python装饰器参数

带有@syntax的python装饰器参数,python,decorator,python-decorators,Python,Decorator,Python Decorators,我正在尝试使用可以接受参数的缓存属性装饰器 我看了一下这个实现: 但我的问题是,如果我想使用参数,我不能用@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参数一起使用 谢谢您

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

我看了一下这个实现:

但我的问题是,如果我想使用参数,我不能用@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'
decorator实际上只是语法糖:

def my_func(self):
    return 'ok'
my_func = cachedProperty(name='test')(my_func)
因此,只要
@
之后的表达式返回您的修饰符[*],表达式本身的实际作用就无关紧要了

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


[*]表达式语法被故意限制在允许的范围内。您可以进行属性查找和调用,就是这样,只允许在虚线名称末尾使用参数进行可选调用(其中点是可选的):


这是一个语法错误。

是的,不起作用,不引用名称。那我怎么才能使用它呢?另外,用类来定义装饰器会更容易吗?使用
(set | get | del)attr
uuu dict_uu
之间有什么区别吗?@rmartinjak:例如,它会绕过任何数据描述符。因此,如果有一个
类型(self).test
属性,
self.\uuu dict\uuu['test']
将直接访问实例属性,而不触发属性。一旦我用参数定义了描述符,即使我想要参数的默认值
@cached\u property()
,我是否总是要用括号调用它?执行
@cached_property
将返回装饰函数。@YAmikep:是,因为否则要装饰的函数将调用
cached_property()
工厂。
def my_func(self):
    return 'ok'
my_func = cachedProperty(name='test')(my_func)
decorator               ::=  "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE)