解读Python函数闭包的概念及作用域

2025-05-06 03:51:36

1、在前面的内容中,我们讨论了全局变量和局部变量的作用域,也讨论了嵌套函数的作用域,并了解了局部变量或嵌套函数仅限于在函数体内使用。但在一些情况下,可以将函数内部的嵌套函数引入到全局环境中使用,Python将引入到全局环境中使用的嵌套函数及其环境变量构建成一个封闭的包,该包内的环境变量不受外部环境的影响,这就是我们将要讨论的闭包。前面我们了解了嵌套函数的作用域仅限于其父函数体内,如果在父函数体外调用其嵌套的函数,就会超出嵌套函数的作用域。

解读Python函数闭包的概念及作用域

2、上面的代码定义了line_conf函数,在line_conf函数体内有嵌套定义了计算直线方程的函数line。依据前面学过的知识,我们会推断出在line_conf函数体内调用line函数是合法的,但在line_conf函数体外调用line函数是非法的,因为在line_conf函数体外调用line函数已经超越了line函数的作用域。上面代码的执行结果也验证了我们的推断。

解读Python函数闭包的概念及作用域

3、在Python语言中,当父函数体内定义了嵌套函数后,父函数可以把定义的嵌套函数作为希巫府浆嵌套函数的引用返回给调用者。函数的引用是什么呢?当我们定义一个函数时,不狃阝垮轹管是父函数还是父函数体内的嵌套函数。Python解释器都会为定义的函数分配内存空间,用于存储函数的代码、使用的变量等等,该内存的地址被赋值给函数名称所标识的存储单元,函数调用者可以通过函数名称所标识的存储单元找到函数的内存地址,并执行该函数。由此看来,函数名称也是一个变量,它存储了函数的内存地址。函数的内存地址既能赋值给函数名称,也可以通过函数名称赋值给其它变量,只不过其它变量存储的不是函数的直接内存地址,而是函数名称的内存地址。例如前面代码定义的line函数,可以把line函数名称的地址赋值给变量a和b,执行a、b、line的效果都是一样的。

解读Python函数闭包的概念及作用域

4、上面的代码把line函数名称分别赋值给局部变量a和b,分别执行line(5)、a(5)、b(5),其执行结果是相同的。由此可以证明,变量a和b与line指向同一个函数。在这种情况下,我们说a和b是line函数的引用。理解了什么是函数的引用后,我们就很容易理解把函数作为一个引用返回给调用者了。当父函数把父函数体内的嵌套函数名称返回给调用者时,实际上是把嵌套函数名称的内存地址返回给调用者,调用者将返回的函数名称内存地址赋值给接收变量,调用者通过接收的变量就可以执行接收变量所引用的函数。

解读Python函数闭包的概念及作用域

5、上面的代码把line_conf函数内部定义的line嵌套函数返回给调用者,调用者将line嵌套函数的内存地址赋值给my_line变量,最后执行my_line所引用的line函数。执行结果如下图所示。

解读Python函数闭包的概念及作用域

6、现在我们已经实现了把父函数中的嵌套函数引入到全局环境中,嵌套函数可以在父函数体外被调用。这已经是闭包的概念了,嵌套函数作为一个独立的执行环境被外部引用,此时被外部环境独立引用的嵌套函数已经脱离了父函数体,构成一个独立的运行环境。我们都知道,局部变量在函数执行完成后就被销毁了。那么,如果在line函数中使用了line_conf的变量,当line_conf函数执行完成后,返回到全局环境的line函数还能使用line_conf的中的变量吗?

解读Python函数闭包的概念及作用域

7、在上面的代码中,line函数使用了其父函数声明的变量b,变量b在line函数的定义易七淄苷之外,此时b为line的环境变量。当line函数作为line_conf挣窝酵聒函数的返回值时,变量b的取值已经和line函数绑定在一起,也就是说父函数和line函数绑定的变量b的值已经没有关系了,变量b即使再有变化,也不会影响到line函数的计算结果。在这种情况下,我们说line函数和它的环境变量b构成了一个闭包,闭包是一个独立的运行环境,不受外部环境的影响和约束。上面的代码输出结果为25,而不是15。下面是简单使用闭包的例子,模拟一个计数器。

解读Python函数闭包的概念及作用域

8、上面的代码定义了counter函数,它所做的事情就是接收一个初始值并开始计数,初始值赋值给列表count的一个成员。然后在内部定义一个嵌套函数incr,incr使用了父函数的局部变量count,count也是incr函数的环境变量,这样就创建了一个闭包,因为incr函数包含了counter函数中局部变量的作用域。下图是上面代码执行后的输出结果。

解读Python函数闭包的概念及作用域
声明:本网站引用、摘录或转载内容仅供网站访问者交流或参考,不代表本站立场,如存在版权或非法内容,请联系站长删除,联系邮箱:site.kefu@qq.com。
猜你喜欢