现在我们已经了解了如何自定义Python装饰器,但应该如何理解装饰器呢?到底是什么原理呢?要想理解Python装饰器,首先应该知道Python函数就是对象,看下面的例子:
- def shout(word="yes"):
- return word.capitalize()
- # 输出:Yes
- print(shout())
- # 将shout函数赋给另一个变量,这里并没有使用圆括号,
- # 所以不是调用函数,而是将函数赋给另一个变量,也就是为函数起一个别名
- scream = shout
- # 可以用scream调用shout函数
- # 输出:Yes
- print(scream())
- # 目前,同一个函数,有两个引用:scream和shout,可以使用del删除一个引用
- del shout
- try:
- # 该引用删除后,就不能通过该引用调用函数了
- print(shout())
- except NameError as e:
- print(e)
- # 仍然可以通过另外一个引用调用函数
- # 输出:Yes
- print(scream())
这段代码演示了把函数作为对象使用。如果加一对圆括号,就是调用函数,如果不加一对圆括号,函数就是对象,可以赋给另一个变量,也可以作为函数参数值传入函数。
由于Python函数本身是对象,所以可以在任何地方定义,包括函数内容,这就是Python内建函数,代码如下:
- def talk():
- # 内嵌函数
- def whisper(word="YES"):
- return word.lower()+"…"
- # 调用内嵌函数
- print(whisper())
- # 调用talk,whisper函数在talk内部被调用
- # 输出:yes…
- talk()
- try:
- # 但whisper函数在talk函数外部并不可见,所以调用会哦抛出异常
- print(whisper())
- except NameError as e:
- print(e)
现在来总结下,Python函数的特性如下:
(1)可以将函数本身赋给一个变量,或作为参数值传入函数(方法);
(2)可以在一个函数(方法)内部定义;
有了这两个特性,就意味着函数可以被另一个函数返回,看下面的代码:
- def getTalk(kind="shout"):
- # 定义第1个内嵌函数
- def shout(word="yes"):
- return word.capitalize()+"!"
- # 定义第2个内嵌函数
- def whisper(word="yes") :
- return word.lower()+"…"
- # 根据参数值返回特定的函数
- if kind == "shout":
- # 这里没有使用一对圆括号,所以不是调用函数,而是返回函数本身
- return shout
- else:
- return whisper
- # talk是函数本身,并没有被调用
- talk = getTalk()
- # 输出函数本身
- # 输出:<function getTalk.<locals>.shout at 0x7f93a00475e0>
- print(talk)
- # 调用talk函数(其实是shout函数)
- print(talk())
- #outputs : Yes!
- # 调用whisper函数
- print(getTalk("whisper")())
在这段代码中,getTalk函数根据kind参数的值返回不同的内嵌函数,所以getTalk函数的返回值是函数本身,或称为函数对象,如果要调用函数,需要使用一对圆括号,如getTalk()()。