繁体   English   中英

如何装饰可调用类的实例?

[英]How can I decorate an instance of a callable class?

def decorator(fn):
    def wrapper(*args, **kwargs):
        print 'With sour cream and chives!',
        return fn(*args, **kwargs)
    return wrapper

class Potato(object):
    def __call__(self):
        print 'Potato @ {} called'.format(id(self))

spud = Potato()
fancy_spud = decorator(Potato())

使用此代码,我们有两个可调用类的实例,一个是装饰的,一个是普通的:

>>> spud()
Potato @ 140408136280592 called
>>> fancy_spud()
With sour cream and chives! Potato @ 140408134310864 called

我想知道是否支持在一个实例的@decorator使用@decorator语法 - 而不是装饰适用于每个实例的类/方法。 根据这个流行的答案,@syntax只是糖:

function = decorator(function)

但这是一种过度简化吗? 我的所有半生不熟的尝试似乎只有在defclass ,whitespace或@another_decorator之前出现语法时才能工作。

@decorator
baked = Potato()

这是一个SyntaxError

baked = Potato()
@decorator
baked

还有SyntaxError

@decorator
def baked(_spud=Potato()):
    return _spud()

工作,但丑陋和有点作弊。

是的,这是过于简单化了。 如果我们查看语法decorator只出现在规则decorators ,它只出现在classdeffuncdef一部分中:

decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
decorators: decorator+
decorated: decorators (classdef | funcdef)

语言参考说的是什么(我认为这是在链接答案中重复的内容)

@f1(arg)
@f2
def func(): pass

相当于

def func(): pass
func = f1(arg)(f2(func))

类似于类定义。 但这并不意味着@decorator语法可以应用于任何地方; 它仅在函数或类定义之前立即生效。

顺便说一下,即使官方文件也不严格正确; 在调用decorator时,函数(或类)没有绑定到封闭的命名空间或范围中,因此给定的语法并不完全等效。

defclass语句有一些有趣的东西,我认为这是它们是@decorator语法支持的唯一语句的部分原因:它们是Python中将名称绑定到知道什么的对象的唯一方法名字是

最后,这是调用您可能喜欢的装饰器的另一种方法:

@decorator
class baked:
    __metaclass__ = lambda *_: Potato()

你质疑:

根据这个流行的答案,@syntax只是糖:

function = decorator(function)

但是,这样说更准确

@decorator
def function():
    pass

语法糖是:

def function():
    pass
function = decorator(function)

装饰器专门用于装饰函数,方法或类定义 引入类装饰器PEP描述了语法:

decorated: decorators (classdef | funcdef)

funcdef: 'def' NAME parameters ['->' test] ':' suite

如您所见,装饰器必须紧跟在classdeffuncdef之前,因此无法直接在可调用类的实例上使用它。

暂无
暂无

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

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