Python嵌套函数(Nested function)和闭包(closure)

Python嵌套函数(Nested function)和闭包(closure)

Python允许函数体中定义函数,内部函数(inner function)也称为嵌套函数(nested function)。

为了执行内部函数,必须调用外部函数。 如果不调用外部函数,内部函数将永远不会执行。不能直接调用内部函数,需要先调用外部函数,在调用内部函数,否则出错。

下面给出一个嵌套函数的示例源码:

def outer(x):	# 外部函数
    print("outer的x:{}".format(x))
    def inner(y):  # 内部函数
        print("inner的y:{}".format(y))
        print("x+y={}".format(x+y))
        
    inner(8)     #调用内部函数

outer(20)  # #调用外部函数

运行测试如下:

典型的闭包(closure)结构

就是在一个外部函数中定义了一个内部函数,内部函数使用了外部函数的局部变量,并且外部函数的返回值是内部函数,这样就构成了一个闭包。

典型的闭包格式的描述:

 def 外层函数():
    外层局部变量
    def 内层函数():
        引用外层函数的局部变量

return 内层函数

将上例嵌套函数修改成闭包结构源码如下:

def outer(x):	# 外部函数
    print("outer的x:{}".format(x))
    def inner(y):	# 内部函数
        print("inner的y:{}".format(y))
        return x + y	# 访问外部函数的参数——这里是x
    
    return inner    	# 通过返回内部函数,实现外部引用——inner后没有括号()

n = outer(20)	# 调用外部函数并传参,获取引用内部函数
m=n(8)	# 调用内部函数inner(y)并传参,原外部函数的参数继续存在
print(m)

运行测试如下:

一般而言,调用一个函数是加一个括号。

如果看见函数括号后还有一个括号,说明第一个函数(外部函数)返回了一个函数(内部函数),前面的括号是外部函数的,后面的括号是内部函数的。

现在,修改上面闭包结构源码调用部分:

def outer(x):	# 外部函数
    print("outer的x:{}".format(x))
    def inner(y):	# 内部函数
        print("inner的y:{}".format(y))
        return x + y	# 访问外部函数的参数——这里是x
    
    return inner    	# 通过返回内部函数,实现外部引用——inner后没有括号()

k=outer(20)(8)
print(k)

运行测试如下:

一般情况下,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。但是,闭包是一种特殊情况,如果外部函数在结束的时候,发现有自己变量将来会在内部函数中用到,就把这个变量同内部函数绑定在一起。这样即使外部函数已经结束了,内部函数仍然能够使用外部函数的变量。

判断函数是否为闭包

可以通过__closure__ 属性来判断,返回的是一个元组,每一项都是闭包函数引用的外部变量,可以通过cell_contents 将被引用的变量打印(显示)出来。

示例源码如下,请留意__closure__、cell_contents的使用:

def outer(x):	# 外部函数

    def inner(y):	# 内部函数
        return x 	# 注意这里:将return x 改为 return y 再运行试试看
    
    return inner    	# inner后没有括号()

n = outer(20)	# 调用外部函数

#查看 __closure__ 的值
print(n.__closure__)

#通过cell_contents 将被引用的变量打印出来
for line in n.__closure__:
print(line.cell_contents)

运行测试如下:

由此可知,闭包的特点是:内部函数必须引用在enclosing scope(外层/封闭作用域)中定义的变量值,并且,enclosing function(外层/封闭函数)必须返回内部函数。

小结

通常情况下,一个 nested function 可以成为一个 closure,但并不是所有的 nested function 都是 closure。
即使 nested function引用了外部的变量,只要它不需要在外部使用,这些变量也不会形成closure。closure是在nested function的基础上,在内部函数中引用了外部函数中的变量并返回该内部函数,从而造成包含自由变量(free variable)的函数对象,这个函数对象不仅仅具有函数的执行代码,而且还保留了自由变量的状态。所谓自由变量,就是在闭包中被引用但没有在闭包中定义的变量,它们的值保存在闭包的环境中,随着闭包的生命周期而存在。

进一步了解

python之 Nested Function
https://blog.csdn.net/cnds123/article/details/129684125

python中闭包详解https://zhuanlan.zhihu.com/p/341376218
Python闭包(Closure) https://www.cnblogs.com/BlueSkyyj/p/8884236.html
python中函数嵌套、函数作为变量以及闭包的原理 https://www.cnblogs.com/xiaxiaoxu/p/9785687.html

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习&实践爱好者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值