Python函数之闭包
1.闭包
由于闭包这个概念比较难以理解,尤其是初学者来说,相对难以掌握,所以我们通过示例去理解学习闭包。
给大家提个需求,然后用函数去实现:完成一个计算不断增加的系列值的平均值的需求。
例如:整个历史中的某个商品的平均收盘价。什么叫平局收盘价呢?就是从这个商品一出现开始,每天记录当天价格,然后计算他的平均值:平均值要考虑直至目前为止所有的价格。
比如大众推出了一款新车:小白轿车。
第一天价格为:100000元,平均收盘价:100000元
第二天价格为:110000元,平均收盘价:(100000 + 110000)/2 元
第三天价格为:120000元,平均收盘价:(100000 + 110000 + 120000)/3 元
........
我们用函数实现上述例题:
-
版本一
series = [] def make_averager(price): series.append(price) total = sum(series) return total / len(series) print(make_averager(100000)) print(make_averager(110000)) print(make_averager(120000)) series列表创建在全局空间,他应该属于我们函数中的一个变量,全局空间的数据会有一个安全隐患,容易被别人修改。 series = [] def make_averager(price): series.append(price) total = sum(series) return total / len(series) print(make_averager(100000)) print(make_averager(110000)) series.append(666) print(make_averager(120000))
-
版本二
函数是独立的功能,我们应该将series放在函数中,形成一体。 def make_averager(price): series = [] series.append(price) total = sum(series) return total / len(series) print(make_averager(100000)) print(make_averager(110000)) print(make_averager(120000)) 版本二,有问题,每次调用函数,都会创建一个临时空间,创建一个新列表,这个列表不会保留之前的数据。
-
版本三
使用闭包。 def make_averager(): series = [] def average(price): series.append(price) total = sum(series) return total / len(series) return average ret = make_averager() # average函数名 print(ret(100000)) print(ret(110000)) print(ret(120000))
-
如何形成闭包函数?
- 闭包函数一定是嵌套中的函数。
- 内层嵌套的函数对外层函数非全局变量的引用。(引用的变量称之为自由变量,也不会消失。)
-
测试:
例一:
def wrapper(): a = 1 def inner(): print(a) return inner ret = wrapper()
例二:
a = 2 def wrapper(): def inner(): print(a) return inner ret = wrapper()
例三:
def wrapper(a, b): """ :param a: 2 :param b: 3 :return: """ # a = 2 # b = 3 def inner(): print(a) print(b) return inner a = 2 b = 3 ret = wrapper(a, b)
-
具体方法判断是不是闭包
def wrapper(a, b): """ :param a: 2 :param b: 3 :return: """ # a = 2 # b = 3 def inner(): print(a) print(b) return inner a = 2 b = 3 ret = wrapper(a, b) 获取闭包函数的自由变量 print(ret.__code__.co_freevars) 获取自由变量具体的值 print(ret.__closure__[0].cell_contents)
-
闭包函数的作用
- 保证数据安全性。
- 闭包可以构建装饰器。