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
我想知道是否支持在一个实例的callable上使用@decorator
语法 - 而不是装饰适用于每个实例的类/方法。根据{{3}}流行的答案,@syntax只是糖:
function = decorator(function)
但这是一种过度简化吗?我的所有半生不熟的尝试似乎只有在def
,class
,空格或@another_decorator
之前语法出现时才有效。
@decorator
baked = Potato()
那是SyntaxError
。
baked = Potato()
@decorator
baked
另外SyntaxError
。
@decorator
def baked(_spud=Potato()):
return _spud()
工作,但是丑陋而且有点作弊。
答案 0 :(得分:4)
是的,这过于简单化了。如果我们查看the grammar,则decorator
仅显示在decorators
规则中,该规则仅作为classdef
或funcdef
的一部分显示:
decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
decorators: decorator+
decorated: decorators (classdef | funcdef)
language reference says(我认为这是在链接答案中重复的内容)是
@f1(arg)
@f2
def func(): pass
相当于
def func(): pass
func = f1(arg)(f2(func))
类似于类定义。但这并不意味着@decorator
语法可以应用于任何地方;它只在函数或类定义之前有效。
顺便说一句,即使官方文件也不严格正确;在调用decorator时,函数(或类)不会绑定到封闭的命名空间或作用域中,因此给定的语法并不完全等效。
def
和class
语句有一些有趣的内容,我认为这是@decorator
语法支持的唯一语句的一部分原因:它们是Python中将名称绑定到知道该名称是什么的对象的唯一方法。
最后,这是另一种调用您可能喜欢的装饰器的方法:
@decorator
class baked:
__metaclass__ = lambda *_: Potato()
答案 1 :(得分:3)
你质疑:
根据这个流行的答案,@syntax只是糖:
function = decorator(function)
然而,更准确地说
@decorator
def function():
pass
是语法糖:
def function():
pass
function = decorator(function)
装饰器专门用于装饰函数,方法或类 definitions 。 PEP that introduced class decorators描述了语法:
decorated: decorators (classdef | funcdef)
funcdef: 'def' NAME parameters ['->' test] ':' suite
如您所见,装饰器必须紧接在classdef
或funcdef
之前,因此无法直接在可调用类的实例上使用它。