美文网首页
Python闭包探幽

Python闭包探幽

作者: Lysias | 来源:发表于2019-08-06 15:41 被阅读0次

我们想生成一组底数不同的指数函数。

Edition 1

def makeFunc():
    return [lambda x: base**x for base in range(5)]

acts = makeFunc()

[act(2) for act in acts]
>> [16, 16, 16, 16, 16]

base都是4,为什么?我推测,出于效率考虑,python函数并不在定义时“解引用”任何变量。也就是说,将base替换为0, 1...4的操作并没有在定义时发生。而在运行时,base已然为4。


下面是makeFunc的字节码,上述行为的线索就在其中。

  2           0 LOAD_CONST               1 (<code object <listcomp> at 0x0000018B42A70300, line 2>)
              2 LOAD_CONST               2 ('makeFunc.<locals>.<listcomp>')
              4 MAKE_FUNCTION            0
              6 LOAD_GLOBAL              0 (range)
              8 LOAD_CONST               3 (5)
             10 CALL_FUNCTION            1
             12 GET_ITER
             14 CALL_FUNCTION            1
             16 RETURN_VALUE

Disassembly of <code object <listcomp> at 0x0000018B42A70300, line 2>:
  2           0 BUILD_LIST               0
              2 LOAD_FAST                0 (.0)
        >>    4 FOR_ITER                16 (to 22)
              6 STORE_DEREF              0 (base)
              8 LOAD_CLOSURE             0 (base)
             10 BUILD_TUPLE              1
             12 LOAD_CONST               0 (<code object <lambda> at 0x0000018B42A70270, line 2>)
             14 LOAD_CONST               1 ('makeFunc.<locals>.<listcomp>.<lambda>')
             16 MAKE_FUNCTION            8
             18 LIST_APPEND              2
             20 JUMP_ABSOLUTE            4
        >>   22 RETURN_VALUE

Disassembly of <code object <lambda> at 0x0000018B42A70270, line 2>:
  2           0 LOAD_DEREF               0 (base)
              2 LOAD_FAST                0 (x)
              4 BINARY_POWER
              6 RETURN_VALUE

注意观察第三段字节码,即<code object <lambda>>部分。这段字节码显示出lambda函数的运行过程:

  • 解引用外部变量(base)
  • 加载本地变量(x)
  • 二元幂运算
  • 返回。

这说明,lambda函数被调用时,名称base的解引用才会发生。如果base在函数定义时就被替换,这里的字节码应该是加载常数才对。

以上讨论让我们对python变量解引用的时机有了如下认识:

python变量在执行时解引用


Edition 2

def makeAction(base):
    return lambda x: base**x

acts = [makeAction(i) for i in range(5)]

[act(2) for act in acts]
>> [0, 1, 4, 9, 16]

为每个lambda制作一个独立的闭包,顺利做出了5个不一样的函数。

相关文章

  • python闭包学习

    参考文章 python闭包python闭包一步一步教你认识Python闭包深入浅出python闭包

  • python函数之闭包

    目录 python函数之闭包什么是闭包python中的namespace闭包的条件闭包的优点 python函数之闭...

  • Python闭包探幽

    我们想生成一组底数不同的指数函数。 Edition 1 base都是4,为什么?我推测,出于效率考虑,python...

  • Python 闭包使用注意点

    1 Python 闭包 今天,聊下 python 的闭包。在函数编程中经常用到闭包。 闭包是什么,它是怎么产生的及...

  • python高级之闭包

    python高级之闭包 什么是闭包? 闭包(closure)是函数式编程的重要的语法结构。闭包也是一种组织代码的结...

  • Python 中的闭包

    Python 中的闭包:+ http://python.jobbole.com/82296/

  • python之理解闭包和装饰器

    python之理解闭包和装饰器 1、闭包函数 1.1 python中函数都是对象 结果: 上面定义一个shut函数...

  • 闭包

    浅谈 python 的闭包思想 首先 python的闭包使用方法是:在方法A内添加方法B,然后return 方法B...

  • 2018-11-20

    python函数的闭包 闭包: 嵌套函数调用外部函数的变量 注意: 闭包必须是内部函数调用外部函数定义的变量,这其...

  • Python 入门之 闭包

    Python 入门之 闭包 1、闭包 (1)在嵌套函数内使用(非本层变量)和非全局变量就是闭包 (2)_ clos...

网友评论

      本文标题:Python闭包探幽

      本文链接:https://www.haomeiwen.com/subject/ocaidctx.html