在Python中,你能编写一个返回非函数对象的装饰器,比如字符串或字典吗?例如,考虑以下代码:
def decorator(function):
return str(function)
@decorator
def foo(bar):
return bar + 1
此代码有效,但它是社区内公认的做法吗?
答案 0 :(得分:4)
引用PEP 0318:
Python 2.4a2中实现的函数装饰器的当前语法是:
@dec2
@dec1
def func(arg1, arg2, ...):
pass
等效:
def func(arg1, arg2, ...):
pass
func = dec2(dec1(func))
没有对变量func的中间分配。
所以,为了回答你的问题,你可以让一个装饰器返回一个不是函数的东西,并且行为是完全定义的。否则,它将不等同于上面的代码。
然而,这样做非常不清楚。人们希望函数装饰器返回函数(或至少是可调用对象)和类装饰器来返回类。如果您偏离这种模式,请自行承担风险 - 如果您的邻居决定从愤怒和挫败中击倒您的隔间,那就是您的问题:)。
答案 1 :(得分:1)
实际上,我会声称从装饰器返回非功能是完全可以接受的。 无意义的装饰器是一个问题,例如抛弃该功能(或大部分功能)的问题。将函数包装在其他东西中的装饰器不仅有用,甚至在标准库中也可以完成:许多functools
装饰器返回一个自定义可调用对象(当然,内部包装了装饰函数)。
当然,还有一点使用装饰器语法会产生误导,因为返回的内容无法合理地解释为装饰函数的替代。例如,我不会使用dis.dis
作为装饰器,尽管它可以工作。它的问题不在于它不返回函数,或者有副作用(许多有用的装饰器都有副作用,例如“注册这个”装饰器)。唯一的问题是它将函数名称绑定到None
而不是有意义的东西。
答案 2 :(得分:1)
对于不依赖于返回函数的装饰器,有一些模糊的用法。并且,是的,要回答你的直接问题,它是完全合法的,但是,不,它并不常见。
例如,您可以使用它们立即调用函数。
def iifb(*args, **kwargs):
def fn(f):
return f(*args, **kwargs)
return fn
@iifb(1,2)
def hash(x, y):
return x ^ y ^ (x << 3) ^ (y >> 1)
print(hash) # prints 10
当然,类是可调用的,所以你可以做同样的事情来立即实例化一个类。