为什么Python装饰器的参数在语法上与没有参数的参数不同?

时间:2013-11-27 05:22:59

标签: python arguments decorator callable

This article,从各种stackoverflow问题中多次链接,描述了带参数的装饰器在语法上与没有参数的装饰器的区别。

  • 没有参数的装饰者:“请注意__init__()是执行装饰的唯一方法,每次调用装饰__call__()时都会调用sayHello()。”
  • 带参数的装饰器:“现在装饰过程调用构造函数,然后立即调用__call__(),它只能接受一个参数(函数对象),并且必须返回替换原始的装饰函数对象。请注意,__call__()现在仅在装饰期间调用一次,之后,您从__call__()返回的修饰函数将用于实际调用。“

文章中给出的解释并没有告诉我为什么语言是这样建立的:

  

虽然这种行为有意义 - 构造函数现在用于捕获装饰器参数,但对象__call__()不能再用作装饰函数调用,因此您必须使用__call__()进行装饰 - 第一次看到它时仍然令人惊讶

此设置有两个相关功能让我感到不舒服:

  1. 为什么提供一种制作无参数装饰器的方法,这不仅仅是指定装饰器的更通用方法的特例?为什么在两者中使用__init____call__,但是它们意味着不同的东西?
  2. 为什么在带有参数的装饰器的情况下使用__call__用于调用装饰函数以外的目的(顾名思义,至少来自无参数情况)?鉴于__call__仅在__init__之后立即调用,为什么不直接将要装饰的函数作为参数传递给__init__并处理__call____init__所发生的一切。 {1}}而不是?

1 个答案:

答案 0 :(得分:9)

这是因为它是在两种情况下都被调用的装饰器对象。为了更清楚,鉴于此:

def my_decorator(a):
    def wrapper(f):
        def wrapped_function():
            return f() + a
        return wrapped_function
    return wrapper

这样:

@my_decorator(5)
def function():
    return 5

相当于:

decorator = my_decorator(5)

@decorator
def function():
    return 5

在无参数情况下发生的事情是装饰器被直接调用,而不必返回一个将对象作为参数进行装饰的函数。