测开之函数进阶篇・第六篇《闭包》

Posted 七月的小尾巴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了测开之函数进阶篇・第六篇《闭包》相关的知识,希望对你有一定的参考价值。

闭包

闭包的概念

一个完整的闭包,必须满足以下三个条件:
1、函数中嵌套函数
2、外层函数返回内存嵌套函数名
3、内存嵌套函数有引用外层的一个非全局变量

def func():

    num = 100

    def count_book():
        print(num)
        print("这个是计算买书方式的函数")
    return count_book


res = func()
res()

下面我们根据上方的代码进行分析:
1、第一个条件,函数中嵌套了一个函数,我们在 func() 函数中嵌套了 count_book() 函数,这个条件满足
2、第二个条件,外层函数返回内存函数的变量名,我们在外层函数中返回了 return count_book
3、第三个条件,内层函数对外部作用域有一个非全局的变量进行引用,可以看到我们在 count_book() 函数中引导了外层的变量 num

因此,满足上方的条件,形成了一个闭包。

闭包的调用方式,和普通的函数调用不同,同上是上方的代码,假设我们是直接调用 func() 函数,从下方图中,我们可以看到,没有任何返回结果。

这个时候我们需要定义一个函数变量去接收func()函数。

res = func()
res()

返回:
100
这个是计算买书方式的函数

Process finished with exit code 0

闭包的内存分配机制

下面我们来看一下这个函数,我们在嵌套函数中,使用了外层函数定义的实参,这个情况,也算是闭包。
那么闭包的作用是是什么呢?


def func(num):

    def count_book():
        print(num)
        print("这个是计算买书方式的函数")
    return count_book


res = func("111")
print(res.__closure__)

在之前我们使用递归函数的时候,每一次执行递归操作时,程序都会在内存中分配一个内存空间,那么这种情况下,是非常占用内存的。
因此,闭包的实现机制时,在我们函数执行的时候,系统会自动分配一块内存,如果要执行函数内部的代码,他会在之前分配的那块内存中读取数据。

以我们上方的代码为例,在运行 func() 函数时,程序首先会 func() 分配一块内存空间,此时 count_book() 还未被执行,是在 func() 的内存内的。当我们需要调用 count_book() 时,我们需要定义一个新的函数变量 res()进行接收,此时系统会给res()也分配一块内存空间。

闭包之所以要求内存嵌套函数有引用外层的一个非全局的变量,是因为假设闭包引用的变量是外层的全局变量,那么当外部对全局变量进行修改的时候,闭包内的数据就会发生改变。

因此当我们执行闭包的时候,闭包内置的 __closure__方法,会对该变量进行锁定,外层无法修改内层的数据,内层的数据也不会对外层发生改变。实现数据的锁定,提高数据的稳定性。

以上是关于测开之函数进阶篇・第六篇《闭包》的主要内容,如果未能解决你的问题,请参考以下文章

测开之函数进阶篇・第五篇《递归函数纯函数匿名函数偏函数》

测开之数据类型进阶篇・第三篇《推导式》

测开之面向对象进阶篇・《多态》

测开之面向对象进阶篇・《属性自省》

测开之面向对象进阶篇・《魔术方法》

测开之数据类型进阶篇・第二篇《字典和集合的原理应用》