【问题标题】:Why does chained assignment work this way? [duplicate]为什么链式赋值会这样工作? [复制]
【发布时间】:2018-02-06 01:06:36
【问题描述】:

我在一篇文章中找到了作业a = a[1:] = [2]。我在python3和python2中试过;一切正常,但我不明白它是如何工作的。 = 这里不像 C 语言; C 从右到左处理=。 python如何处理=运算符?

【问题讨论】:

  • 我重新打开了这个问题,因为它比How do chained assignments work? 中解决的典型x = y = some_func() 案例复杂得多
  • 它可以从左到右,因为赋值是 Python 中的一种语句,而不是 C 中的表达式。它不具有关联性,因为 a = b = … = x 都被一起解析。
  • 这个问题只与非复杂部分有关(从左到右)。 OP 表示他们了解它的工作原理。不过,我并不强烈反对重新开放。

标签: python python-3.x python-2.7


【解决方案1】:

the language docs on assignment:

赋值语句计算表达式列表(请记住,这可以是单个表达式或逗号分隔的列表,后者产生一个元组)并将单个结果对象从左到右分配给每个目标列表。

在这种情况下,a = a[1:] = [2] 有一个表达式列表 [2],以及两个“目标列表”aa[1:],其中a 是最左侧的“目标列表”。

您可以通过查看反汇编来了解其行为方式:

>>> import dis
>>> dis.dis('a = a[1:] = [2]')
  1           0 LOAD_CONST               0 (2)
              2 BUILD_LIST               1
              4 DUP_TOP
              6 STORE_NAME               0 (a)
              8 LOAD_NAME                0 (a)
             10 LOAD_CONST               1 (1)
             12 LOAD_CONST               2 (None)
             14 BUILD_SLICE              2
             16 STORE_SUBSCR
             18 LOAD_CONST               2 (None)
             20 RETURN_VALUE

(反汇编的最后两行可以忽略,dis正在做一个函数包装器来反汇编字符串)

需要注意的重要部分是,当您执行 x = y = some_val 时,some_val 被加载到堆栈中(在本例中由 LOAD_CONSTBUILD_LIST),然后堆栈条目被复制并分配,从从左到右,到给定的目标。

所以当你这样做时:

a = a[1:] = [2]

它对包含2 的全新list 进行了两次引用,第一个操作是STORE 其中一个对a 的引用。接下来,它存储了对a[1:] 的第二个引用,但是由于切片赋值本身会发生变异a,它必须再次加载a,从而得到刚刚存储的list。幸运的是,list 对自切片分配具有弹性,否则我们会遇到问题(它将永远读取它刚刚添加的值以添加到末尾,直到我们用完内存并崩溃);实际上,它的行为就像分配了 [2] 的副本以替换从索引 1 开始的所有元素。

最终结果相当于你已经完成了:

_ = [2]
a = _
a[1:] = _

但它避免使用_ 名称。

要清楚,反汇编注释:

列出[2]:

  1           0 LOAD_CONST               0 (2)
              2 BUILD_LIST               1

复制对[2]的引用:

              4 DUP_TOP

执行存储到a:

              6 STORE_NAME               0 (a)

执行存储到a[1:]:

              8 LOAD_NAME                0 (a)
             10 LOAD_CONST               1 (1)
             12 LOAD_CONST               2 (None)
             14 BUILD_SLICE              2
             16 STORE_SUBSCR

【讨论】:

    【解决方案2】:

    我理解此类分配的方式是,这相当于

    temp = [2]
    a = temp
    a[1:] = temp
    

    [2, 2] 的结果值与此解释一致。

    【讨论】:

      猜你喜欢
      • 2020-06-08
      • 2016-07-12
      • 2019-05-20
      • 1970-01-01
      • 2015-12-23
      • 1970-01-01
      • 1970-01-01
      • 2016-10-04
      相关资源
      最近更新 更多