迭代器,生成器,装饰器,号称python的三大利器。今天,来谈谈三大利器之一的装饰器。
所谓装饰器,就是在不改变一个函数内部代码的前提下,给函数额外增加功能的东西。装饰器本质就是一个嵌套函数。
要实现装饰器的功能,就不得不提到闭包这个东西了。
闭包,通俗来说,就是一个函数形式,它可以拥有自己的一些属性和方法,但仅限于自己定义的,而不会像类那样,拥有继承自object的所有属性和方法。最简单的闭包实现需要嵌套两层函数,比如下面这个demo:
def closure(func): # 将函数的引用当做形参传进内层函数,内层函数调用
def demo():
func()
print("hello closure")
return True
return demo
在上面这段代码中,外层函数closure的返回值是内层函数demo的引用,内层函数调用了外层函数得到的参数,并实现了一些功能。
如果closure(func)中传入的参数是另一个函数的引用,就可以在demo()中实现该func的调用,这样一来,一个装饰器就实现了。
== 这其中,最关键的一点是:外层函数要返回内层函数的引用,并且要传入外界函数的引用==
下面这段代码完整展示了一个装饰器的定义和作用实现:
# -*- coding: utf-8 -*-
def closure(func): # 将函数的引用当做形参传进内层函数,内层函数调用
def demo():
print("hello closure!")
func()
return demo
def test1():
print("hello world!")
@closure
def test2():
print("hello world!")
# 上面的@等价于下面这句
# test = closure(test)
test1()
print("-------------")
test2()
执行@closure具体过程是:
首先找到test2,然后把test2当做实参传递给closure(),这样,demo()就可以通过func,调用test2。所以整个过程就表现为:先把closure给执行了,然后test2这个变量被重定向到了demo。
最后运行结果就是:
hello world
-------------
hello world!
hello closure!
特别的:装饰器并不是在函数电泳的时候开始执行,而是在函数定义后就开始装饰函数了。下面这段代码说明了这个道理|:
# -*- coding: utf-8 -*-
def closure(func): # 将函数的引用当做形参传进内层函数,内层函数调用
print("开始装饰")
def demo():
print("hello closure")
func()
print("装饰完成")
return demo
def test1():
print("hello world")
@closure
def test2():
print("hello world!")
运行结果是这样的:
具体效果读者可自行尝试。