【问题标题】:Behind the scene of nested operation in PythonPython中嵌套操作的幕后花絮
【发布时间】:2019-07-27 17:25:09
【问题描述】:

我们知道,对于一个操作,我们可以编写如下代码:

a = [1, 2, 3]
b = 2
c = sum(a)
result = c**b

或者它可以在一行中计算result

a = [1, 2, 3]
b = 2
result = sum(a)**b

在第一种情况下,sum(a) 被计算,并以变量名称 c 放置在内存中,并被检索用于计算 result。在后一种情况下,python 解释器是为sum(a) 创建一个临时变量还是在幕后发生了其他事情?

【问题讨论】:

  • 调用 sum(a) 时有一个默认值 0 将由 sum 函数定义,因此实际上您正在调用 sum(a,0),因此 python 会将 0 放入内存中将 a 中的每个项目添加到其中。希望有帮助
  • @basilisk。感谢您的评论。我确实是指在后一种情况下sum(a) 的存储方式和位置。

标签: python python-internals


【解决方案1】:

第二种情况,Python解释器(基于栈)将sum的结果存储在栈中,然后在加载名称b的值后进行幂运算。

您可以检查字节码以确切了解它是如何完成的:

In [182]: def one(): 
     ...:     a = [1, 2, 3] 
     ...:     b = 2 
     ...:     c = sum(a) 
     ...:     return c**b 
     ...:

In [183]: def two(): 
     ...:     a = [1, 2, 3] 
     ...:     b = 2 
     ...:     return sum(a)**b 
     ...:

In [184]: dis.dis(one)
  2           0 LOAD_CONST               1 (1)
              2 LOAD_CONST               2 (2)
              4 LOAD_CONST               3 (3)
              6 BUILD_LIST               3
              8 STORE_FAST               0 (a)

  3          10 LOAD_CONST               2 (2)
             12 STORE_FAST               1 (b)

  4          14 LOAD_GLOBAL              0 (sum)
             16 LOAD_FAST                0 (a)
             18 CALL_FUNCTION            1
             20 STORE_FAST               2 (c)

  5          22 LOAD_FAST                2 (c)
             24 LOAD_FAST                1 (b)
             26 BINARY_POWER
             28 RETURN_VALUE

In [185]: dis.dis(two)
  2           0 LOAD_CONST               1 (1)
              2 LOAD_CONST               2 (2)
              4 LOAD_CONST               3 (3)
              6 BUILD_LIST               3
              8 STORE_FAST               0 (a)

  3          10 LOAD_CONST               2 (2)
             12 STORE_FAST               1 (b)

  4          14 LOAD_GLOBAL              0 (sum)
             16 LOAD_FAST                0 (a)
             18 CALL_FUNCTION            1
             20 LOAD_FAST                1 (b)
             22 BINARY_POWER
             24 RETURN_VALUE

具体看two上缺少以下两个字节码:

             20 STORE_FAST               2 (c)

  5          22 LOAD_FAST                2 (c)

由于第二种情况不需要局部变量c的存储加载,所以也比第一种要快。

【讨论】:

  • @heemayl。谢谢你。那么如果一行中有多个嵌套操作,解释器如何知道它们存储在哪里呢?
  • @Khani:当 Python 代码被转换为字节码时,编译器会在任何给定时间跟踪堆栈上的内容,并确保每个操作都能看到它期望的值,在右边订购。
猜你喜欢
  • 1970-01-01
  • 2018-09-15
  • 2011-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-20
  • 1970-01-01
  • 2017-05-03
相关资源
最近更新 更多