Python装饰器可以用来返回非函数对象吗?

时间:2013-12-26 20:49:14

标签: python

在Python中,你能编写一个返回非函数对象的装饰器,比如字符串或字典吗?例如,考虑以下代码:

def decorator(function):
    return str(function)

@decorator
def foo(bar):
    return bar + 1

此代码有效,但它是社区内公认的做法吗?

3 个答案:

答案 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

当然,类是可调用的,所以你可以做同样的事情来立即实例化一个类。