装饰器 闭包
Python的装饰器、闭包是进入Python高级语法的基础,使用在使用装饰器之前,有以下条件:
- 存在闭包
- 存在需要被装饰的函数
- 理解函数地址值的概念
函数的地址值
众所周知,我们定义函数后,函数名加()既可以调用函数,那么如果我们尝试打印一下函数名呢?
def test():
pass
# 不需要括号
print(test)
运行结果:
<function test at 0x00000211A7B56160>
也就是说,每个函数名字都存放着它的地址值。
闭包
闭包可以理解成“定义在一个函数内部的函数“。
在一个函数中嵌套定义了一个函数,内函数里运用了外函数的临时变量,并且 外函数的返回值(return)是内函数的引用。这样就构成了一个闭包 。
话不多说,我们上代码:
条件:
- 存在函数的嵌套关系
- 内层函数引用了外层函数的变量
- 外层函数返回内层函数的地址值
# 闭包的构成
def out_func(num):
def in_func(in_num):
print("内嵌函数in_num:", in_num)
print("外嵌函数:out:", num) # 此行调用外部函数的局部变量
# 注意返回值没有小括号
# 实际上会返回in_func的地址值
return in_func
in_def = out_func(10)
# 此时in_def接收了内嵌函数的地址值
# 使用此变量加上()运行它
# 需要传一个in_num参数
in_def(5)
运行结果:
内嵌函数in_num: 5
外嵌函数:out: 10
装饰器
在不修改源代码的基础上,给函数增加新的功能。
装饰器会将被装饰的函数当作参数传递给装饰器同名的函数。
添加装饰器,需要:
- 存在闭包
- 存在需要被装饰的函数
例如我们想给一个函数增加一个打印“欢迎光临”的功能,在原则上我们是不会去修改原函数的代码内容的,那么怎么实现呢?我们可以使用装饰器,给函数添加功能。
语法:@闭包的外层函数名
写在被装饰函数的上一行
def out_func(func):
# 传入的func是被装饰的函数
def in_func():
print("欢迎光临!")
# 调用被装饰的函数,实现两个函数的内容都被调用
func()
# 注意返回值没有小括号
# 实际上会返回in_func的地址值
return in_func
# 添加装饰器
# @闭包的外层函数名
@out_func
# 装饰器会把login()函数传给out_func()
def login():
print("登陆成功")
运行结果:
欢迎光临!
登陆成功
这样就实现了不修改原函数的基础上又增加了新的功能。