python(二十)——闭包

java中的闭包在jdk1.8之后才出现。
:函数inner在函数outter里面

def outter():
    def inner():
        pass
    pass

定义

百度百科上的定义

闭包包含自由(未绑定到特定对象)变量,这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)。

inner就是闭包

自由变量outter里的变量,作用域属于 enclosing

我对闭包的理解

  • inner能够访问outter里的变量var_outs
  • inner的计算环境指var_outs。通过一些写法,inner将计算结果保存在var_outs(将var_outs更新了)中;inner被再次调用时,可继续使用var_outs。这称为保存inner的当前运行环境
  • 外部直接调用inner
  • 大概是嵌套函数的妙用

例子

在平面直角坐标系中移动,每次移动都需要在上一次移动结束的位置开始:
通过函数outter中的变量position函数inner成功保存了每次移动后的位置

# 闭包函数
origin = [0, 0] # 原点

def outter(position=origin):
	# position为当前位置
    def inner(direction, step):
    	# direction为移动方向
    	# step为移动步长
        # 保存当前位置
        position[0] = position[0] + direction[0] * step
        position[1] = position[1] + direction[1] * step
        return position
    return inner

inn = outter()
print(inn((0, 1), 10)) # 沿y轴走10步
print(inn((1, 0), 10)) # 沿x轴走10步
print(inn((0, 1), 20)) # 沿y轴走20步

在这里插入图片描述

函数的__closure__属性

其存储了闭包中关于自由变量的东西

  • 是个tuple,存储的是cell对象。一个cell对象,存储一个inner的自由变量
  • 只对闭包有效
  • __closure__[index].cell_contents访问第index个自由变量的值
def outter(position=origin):
    c = 1
    b = 2

    def inner(direction, step):
        nonlocal c, b
        b = b
        c = c
        position[0] = position[0] + direction[0] * step
        position[1] = position[1] + direction[1] * step
        return position

    return inner


inn = outter()
print(inn([1, 0], 10)) # [10, 0]
print(outter.__closure__) # none 也就是说这个属性只作用在闭包上
print(type(inn.__closure__)) # tuple,存储了inner的所有自由变量
print(len(inn.__closure__)) # 3
print(inn.__closure__[0]) # <cell at 0x000002D62D427E88: list object at 0x000002D62B5D6208>
print(inn.__closure__[0].cell_contents) # 2,是b的值,表示自由变量的存储是按字母表顺序

这解释了为什么局部变量脱离函数之后,还可以在函数之外被访问的原因的,因为它存储在了闭包的 cell_contents中了。

参考

Python中的闭包
一步一步教你认识Python闭包

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值