闭包与装饰器
- 知识目标
- 知识点
- ①函数作用域
- ②闭包含义
- ③显式查看闭包
- ④闭包由来
- ⑤闭包的应用
知识目标
1、理解函数的作用域;
2、掌握闭包的概念;
3、理解闭包名称的由来;
4、能够利用闭包解决实例问题。
知识点
①函数作用域
Python中函数的作用域由def关键字界定,函数内的代码访问变量的方式是从其他所有层级由内向外
def line_conf(a, b):
def line(x):
return a * x + b
return line
# 定义两条直线
line_A = line_conf(2, 1) # y=2x+b
line_B = line_conf(3, 2) # y=3x+2
# 打印x对应y的值
print(line_A(1)) # 3
print(line_B(1)) # 5
嵌套函数line中的代码访问了a和b变量,line本身函数体内并不存在这两个变量,所有会逐级向外查找,往上走一层就找到了来自主函数line_conf传递a,b。若往外直至全局作用域都查找不到的话代码就会抛出异常
②闭包含义
Python支持使用嵌套函数。如果在一个内部函数中对外部函数作用域(非全局变量域)的变量进行引用,那么内部函数就会被称为闭包。
注意:闭包函数引用的外部变量不一定就是其父函数的参数,也可以是父函数作用域内的任意变量。
def line_conf():
a=1
b=2
def line(x):
print(a*x+b)
return line
line=line_conf()
line(3)
③显式查看闭包
_ closure _属性返回的是一个元组对象,包含了闭包引用的外部变量
def line_conf():
a=1
b=2
def line(x):
print(a*x+b)
return line
line=line_conf()
print(line.__closure__)
for i in line.__closure__: #打印引用的外部变量值
print(i.cell_contents)
若主函数的闭包不引用外部变量,就不存在闭包,主函数的_closure_属性永远为None。
若主函数没有return子函数,就不存在闭包,主函数不存在_closure_属性
④闭包由来
def line_conf(a):
b=1
def line(x):
return a*x+b
return line
line_A=line_conf(2)
b=20
print(line_A(1)) #3
line_A对象作为line_conf返回的闭包对象,它引用了line_conf下的变量b=1,在print时,全局作用域下定义了新的b变量指向20,最终结果仍然引用的line_conf内的b。这是因为,闭包作为对象被返回时,它的引用变量就已经确定(已经保存在它的_closure_属性),不会再被修改。
闭包在被返回时,它的所有变量就已经固定,形成了一个封闭的对象,这个对象包含了其 引用的所有外部,内部变量和表达式。当然,闭包的参数例外。
⑤闭包的应用
闭包实现快速给不同项目记录日志: