python 闭包 装饰器
闭包
在python中一切皆对象,这样就使得变量所拥有的属性,函数也同样拥有。这样我们就可以理解在函数内创建一个函数的行为是完全合法的。这种函数被叫做内嵌函数,这种函数只可以在外部函数的作用域内被正常调用,在外部函数的作用域之外调用会报错.而如果内部函数里引用了外部函数里定义的对象(甚至是外层之外,但不是全局变量),那么此时内部函数就被称为闭包函数。闭包函数所引用的外部定义的变量被叫做自由变量。闭包从语法上看非常简单,但是却有强大的作用。闭包可以将其自己的代码和作用域以及外部函数的作用结合在一起。
1. 函数引用
def test1():
print("--- in test1 func----")
# 调⽤函数
test1()
# 引⽤函数
ret = test1
print(id(ret))
print(id(test1))
#通过引⽤调⽤函数
ret()
运行结果:
>>>
--- in test1 func----
140212571149040
140212571149040
--- in test1 func----
2.什么是闭包
- 函数嵌套
- 往往内函数使用外函数的自由变量
- 外函数返回内函数的引用
# 定义一个函数 求 y = Kx + b 的值
# –*– coding: utf-8 –*–
# @Time : 2019/2/23 20:34
# @Author : Damon_duanlei
# @FileName : bibao_test.py
# @BlogsAddr : https://blog.csdn.net/Damon_duanlei
def line(k, b):
def creat_y(x):
print(k * x + b)
return creat_y
if __name__ == '__main__':
line_a = line(6, 2)
line_a(3)
line_b = line(2, 5)
line_b(5)
运行结果:
>>>
20
15
闭包执行原理:(上文代码为例)
- 代码从上向下执行,运行到第9行代码,发现定义了一个函数,系统不会进入函数执行,而是跳过此段函数代码继续向下执行第15行代码.
- 当系统运行到第 16 行代码, 发现此行代码调用上方定义的函数, 便带着参数 k = 6, b = 2跳到第 9 行执行函数.
- 外部函数(line)执行到第 10 行, 再次发现定义函数, 系统继续跳过定义函数阶段代码向下执行第12行 return 语句, 将内函数引用返回给第 16 行定义的变量.
- 系统向下执行第 17 行代码, 通过引用调用内函数 create_y ,执行过程中内函数未发现变量 k b 就会向上一层(外层)函数中寻找变量k和b , 找到后执行完内函数打印结果. 至此完成一个闭包过程
- 代码继续向下执行到第 18行, 如上流程在执行一次.
总结: 函数, 匿名函数, 闭包, 对象的区别
函数: 普通函数能够完成较为复杂的功能, 普通函数传递的是这个函数的引用,只有功能.
匿名函数: 匿名函数能够完成较为简单的功能, 匿名函数传递的是这个函数的引用,只有功能.
闭包: 闭包能够完成较为复杂的功能, 闭包传递的是这个比保重的函数以及数据,因此传递的事功能+数据
对象:对象能够完成最为复杂的功能,对象传递所有的属性和方法,但是占用较大资源
3 闭包结构中修改外部函数中的变量
类似于函数中修改全局变量使用globle ,在闭包中使用 nonlocal(python3) 可以修改外部函数中的变量
def counter(start=0):
def incr():
nonlocal start
start += 1
return start
return incr
c1 = counter(<