python代码:闭包closure的一个例子

python代码:闭包closure的一个例子

#!/usr/bin/python
# -*- coding: UTF-8 -*-
"""
@author:
@file:closureExample.py
@time:2022-04-03 12:26
"""
# 书《Python核心编程(第二版).pdf》,作者:Wesley J. Chun
# 例子:这个例子说明了如何能通过使用函数的__closure__属性来追踪闭包变量。
"""
python闭包closure

在讨论闭包之前,先总结一下python的命名空间namespace,一般的语言都是通过namespace来识别名字标识,无论是变量,对象,函数等等。
python划分3个名字空间层次,
local:局部,标识为当前函数内,当前类内,比如局部变量。
global:全局,标识当前模块,也就是当前文件,比如全局变量等。
最后一类 built-in,内建,这个是作用域比较大,跨模块(文件)都可以标识,比如我们自建的文件中,引用内建函数dir(), 这就是一个典型的例子,自建的文件中能够并没有声明dir(),但由于dir()是built_in内建函数,故在所有文件或模块都可以引用。
----
再来讨论闭包:
closure概念:在一个内部函数中,对外部作用域的变量进行引用,那么内部函数就被认为是closure(闭包)
自由变量:定义在外部函数内,被内部函数引用或者使用的变量为自由变量

什么是自由变量?下面是关于自由变量在 Python 官方文档中的解释。
如果名称绑定在一个代码块中,则为该代码块的局部变量,除非声明为 nonlocal 或 global 。
如果名称绑定在模块层级,则为全局变量 (模块代码块的变量既为模块局部变量又为全局变量) 。
如果变量在一个代码块中被使用但不是在其中定义,则为自由变量。

结合namespace的概念,自由变量的位置:既不在函数local范围内,也不在全局global范围内,而是在两个函数的作用域之间。
----
所以简单地说,闭包从形式上说,就是函数内嵌一个函数。但是还需满足两个条件,
1.内层函数引用环境变量(自由变量)
2.外部函数返值为内部函数名(一个返回函数的高阶函数)
----
再来说闭包有什么用?
闭包减少了参数的传递数量, 设计闭包是为了增加代码重复利用。
"""

output = '<int %r id=%#0x val=%d>'
w = x = y = z = 1

def f1():
    x = y = z = 2

    def f2():
        y = z = 3

        def f3():
            z = 4
            print(output % ('w', id(w), w))
            print(output % ('x', id(x), x))
            print(output % ('y', id(y), y))
            print(output % ('z', id(z), z))

        clo = f3.__closure__
        if clo:
            print("f3 closure vars: ", [str(c) for c in clo])
        else:
            print("no f3 closure vars")
        f3()

    clo = f2.__closure__
    if clo:
        print("f2 closure vars: ", [str(c) for c in clo])
    else:
        print("no f2 closure vars")
    f2()

clo = f1.__closure__
if clo:
    print("f1 closure vars: ", [str(c) for c in clo])
else:
    print("no f1 closure vars")
f1()

"""
Output:
no f1 closure vars
f2 closure vars:  ['<cell at 0x0000027F1B58AFD0: int object at 0x0000027F0A266950>']
f3 closure vars:  ['<cell at 0x0000027F1B58AFD0: int object at 0x0000027F0A266950>', '<cell at 0x0000027F1B58AF70: int object at 0x0000027F0A266970>']
<int 'w' id=0x27f0a266930 val=1>
<int 'x' id=0x27f0a266950 val=2>
<int 'y' id=0x27f0a266970 val=3>
<int 'z' id=0x27f0a266990 val=4>
"""

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值