解释python decorator的工作原理

Explain how Python decorator works

本问题已经有最佳答案,请猛点这里访问。

这是python decorator的一个示例。我无法理解它的工作方式。请向我解释给定示例的控制流。我将不胜感激。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def helloSolarSystem(original_function):
   def new_function(*args, **kwargs):
        original_function(*args, **kwargs)  
        print("Hello, solar system!")
   return new_function

def helloGalaxy(original_function):
    def new_function(*args, **kwargs):
        original_function(*args, **kwargs)  
        print("Hello, galaxy!")
    return new_function

@helloGalaxy
@helloSolarSystem
def hello(targetName=None):
     if targetName:
        print("Hello," +  targetName +"!")
     else:
        print("Hello, world!")
hello("Earth")


decorator是在python中应用高阶函数的语法糖。高阶函数是将一个或多个函数作为输入并返回函数的函数。即

1
h(x) = f(g(x))

这里,f()是一个高阶函数,它接受单个参数的函数g(x)并返回单个参数的函数h(x)。你可以把f()看作是修改g()的行为。

高阶函数是可组合的(根据定义),因此在您的特定示例中,decorator语法,

1
2
3
4
@helloGalaxy
@helloSolarSystem
def hello(targetName=None):
    ...

相当于,

1
hello = helloGalaxy(helloSolarSystem(hello))

hello代入helloSolarSystem中,再将结果代入helloGalaxy中,得到等价函数调用。

1
2
3
4
5
6
7
def hello(targetName=None):
    if targetName:                            |        
        print("Hello," + targetName +"!")   |  (1)  |
    else:                                     |       |  (2)   |
        print("Hello, world!")                |       |        |  (3)
    print("Hello, solar system!")                     |        |
    print("Hello, galaxy!")                                    |

其中(1)是原始hello()的应用,(2)是,

1
2
3
4
5
def helloSolarSystem(original_function):
    def new_function(*args, **kwargs):
        original_function(*args, **kwargs)   <-- (1)
        print("Hello, solar system!")
    return new_function

以及(3)的应用,

1
2
3
4
5
def helloGalaxy(original_function):
    def new_function(*args, **kwargs):
        original_function(*args, **kwargs)   <-- (2)
        print("Hello, galaxy!")
    return new_function

这只是观察到,在Python中,函数和其他一切一样是对象。啊,包含变量的函数,你没那么特别!

1
2
3
4
5
6
7
8
>>> issubclass(int, object) # all objects in Python inherit from a common baseclass
True
>>> def foo():
...     pass
>>> foo.__class__ # 1
<type 'function'>
>>> issubclass(foo.__class__, object)
True

在你的例子中,@hellogalaxy暗示hello=hellogalaxy(hello)

同样,@hellosolarsystem暗示hello=hellosolarsystem(hello)

当你打电话

@螺旋轴

@hellosolarSystem before hello()函数

你好将由hellogalaxy和hellosolarsystem装饰

因此,新的_函数()将被hellosolarSystem()重写。

在hello("earth")被称为函数hello之前,hello由hellosolarsystem()的newfunction()和hellogalaxy()修饰器修饰。