通过一段简单的代码理解python中的闭包

通过一段简单的代码理解python中的闭包

引例

  • 假设学校每个学期有n次考试,我们需要写一个程序来计算一个学生的前a(a<=n)次考试的平均成绩。
  • 每出一次成绩,只需要将当次的成绩输入电脑,就可以得到平均成绩
  • 代码运行在学校的服务器上,于是有了以下代码:
def caculate(score):
    sum = 0
    ls.append(score)
    for i in ls:
        sum += i
    return sum/len(ls)


if __name__ == '__main__':
    ls = []
    print(caculate(10))
    print(caculate(12))
    print(caculate(15))

分析

  • 上面的代码可以解决问题,但仍然存在一个问题,那就是将存放成绩的列表当做全局变量,这样做会有一个问题,就是可以被很轻易地篡改。一旦被有心人篡改会非常严重,所以我们需要隐藏列表。
  • 隐藏列表,无非就是将列表放在函数作用域中,这样就不能被轻易访问了。
  • 但问题也会同样存在,函数的内存空间是在执行时被创建的,并且一旦执行结束,函数所占的内存就会被回收,那么保存在函数中的列表中的数据也会被清空。

使用闭包的代码:

def average():
    # 用于储存每一次的成绩
    ls = []
    # 向列表中添加数据,并计算平均值
    def caculate(score):
        sum = 0
        ls.append(score)
        print(ls)
        for i in ls:
            sum += i
        return sum/len(ls)
    return caculate



if __name__ == '__main__':
    caculate = average()
    print(caculate(10))
    print(caculate(15))
    print(caculate(20))
    
# 打印结果
[10]
10.0
[10, 15]
12.5
[10, 15, 20]
15.0
  • 我们可以看到,成绩列表中的数据并没有被清除

原理

  • 因为caculate函数使用了average函数中的ls变量,所以average函数产生的内存空间会一直存在(这其实就是闭包),等待caculate函数使用,而average函数返回了caculate函数的引用(函数名),这样我们就可以在全局中通过caculate函数操作ls变量,
  • 虽然也可以操作但只能添加数据,而不能随意更改数据,这样安全性就得到了提升
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章