Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python交换列表_Python_List_Iterable Unpacking_Python Internals - Fatal编程技术网

Python交换列表

Python交换列表,python,list,iterable-unpacking,python-internals,Python,List,Iterable Unpacking,Python Internals,在python中,当我将一个列表分配给另一个列表时,如: a = [1,2,3] b = a 现在b和a指向同一个列表。现在考虑两份清单 a = [1,2,3] b = [4,5,6] a,b = b,a 现在,它们如何像任何其他数据类型一样进行交换,而不是最终都指向同一个列表?看起来像Python在内部交换这些项。检查此程序 a, b = [1, 2], [2, 3] def func(): a, b = b, a import dis dis.dis(func) a, b,

在python中,当我将一个列表分配给另一个列表时,如:

a = [1,2,3]
b = a
现在b和a指向同一个列表。现在考虑两份清单

a = [1,2,3]
b = [4,5,6]
a,b = b,a

现在,它们如何像任何其他数据类型一样进行交换,而不是最终都指向同一个列表?

看起来像Python在内部交换这些项。检查此程序

a, b = [1, 2], [2, 3]

def func():
    a, b = b, a

import dis
dis.dis(func)
a, b, c, d = [1, 2], [2, 3], [4, 5], [5, 6]

def func():
    a, b, c, d  = d, c, b, a

import dis
dis.dis(func)
输出

  4           0 LOAD_FAST                0 (b)
              3 LOAD_FAST                1 (a)
              6 ROT_TWO             
              7 STORE_FAST               1 (a)
             10 STORE_FAST               0 (b)
             13 LOAD_CONST               0 (None)
             16 RETURN_VALUE
  4           0 LOAD_FAST                0 (d)
              3 LOAD_FAST                1 (c)
              6 LOAD_FAST                2 (b)
              9 LOAD_FAST                3 (a)
             12 BUILD_TUPLE              4
             15 UNPACK_SEQUENCE          4
             18 STORE_FAST               3 (a)
             21 STORE_FAST               2 (b)
             24 STORE_FAST               1 (c)
             27 STORE_FAST               0 (d)
             30 LOAD_CONST               0 (None)
             33 RETURN_VALUE
因此,Python将引用
b
a
推到堆栈中。因此,现在最上面的元素是
a
指向的引用,下一个元素是
b
指向的引用。然后,它使用交换堆栈顶部的两个元素。因此,现在,最上面的元素是
b
指向的引用,下一个元素是
a
指向的引用,然后将堆栈的前两个元素分别分配给
a
b

这就是当我们处理的项目数少于4项时,在赋值语句中排序的方式

如果项目数大于或等于四个,它将构建一个元组并解压缩值。检查此程序

a, b = [1, 2], [2, 3]

def func():
    a, b = b, a

import dis
dis.dis(func)
a, b, c, d = [1, 2], [2, 3], [4, 5], [5, 6]

def func():
    a, b, c, d  = d, c, b, a

import dis
dis.dis(func)
输出

  4           0 LOAD_FAST                0 (b)
              3 LOAD_FAST                1 (a)
              6 ROT_TWO             
              7 STORE_FAST               1 (a)
             10 STORE_FAST               0 (b)
             13 LOAD_CONST               0 (None)
             16 RETURN_VALUE
  4           0 LOAD_FAST                0 (d)
              3 LOAD_FAST                1 (c)
              6 LOAD_FAST                2 (b)
              9 LOAD_FAST                3 (a)
             12 BUILD_TUPLE              4
             15 UNPACK_SEQUENCE          4
             18 STORE_FAST               3 (a)
             21 STORE_FAST               2 (b)
             24 STORE_FAST               1 (c)
             27 STORE_FAST               0 (d)
             30 LOAD_CONST               0 (None)
             33 RETURN_VALUE
因为Python赋值首先计算右侧表达式,然后将结果应用于左侧目标

因此,首先,Python将
(,)
创建为一个元组,然后将该元组中的第一项分配给
a
,将该元组中的第二项分配给
b
。这将整齐地交换引用

您可以展开作业,如下所示:

tmp = b, a
a = tmp[0]
b = tmp[1]
现在,它们如何像任何其他数据类型一样进行交换,而不是最终都指向同一个列表


因为从解包元组
b,a
到元组
a,b
的那一刻起,您就失去了对原始
a
b
的引用,它们被重新分配。

看起来Python没有在这里创建元组。请检查我的答案。没有,因为作业已优化。该评论(在我的手机上)发布得有点早。任务优化;当使用多个赋值时,编译器跳过创建元组。没有意义。但是为了理解发生了什么,想象它是一个元组是很好的。在扩展的赋值示例中,
tmp
是一个tuple.Yup。这是我最初的理解。即使是我的第一次编辑也只有基于元组的答案。我只是简单地试了一下dis,结果大吃一惊@SteveJessop:编译器在这两种情况下都会生成一个
BUILD\u TUPLE
操作码,但是当LHS上有赋值且只涉及3或2个值时,窥视孔优化器会用
ROT\ucode>操作码替换该操作码。对于更多的元素,元组仍然是实际创建的。@MartijnPieters这就是为什么我必须用粗体制作
引用。@MartijnPieters得到了你:)请检查我更新的答案,包括元组解包的内容。至于我所说的优化;实际上,它仅限于两个和三个项目的拆包;看看你是否感兴趣。对于两个项目,
BUILD\u TUPLE
UNPACK\u SEQUENCE
替换为
ROT\u two
,对于三个项目,替换为
ROT\u two
。因为4个项目将需要三个操作码(
ROT_-FOUR
,然后
ROT_-FOUR
然后
ROT_-FOUR
),因此不再值得为其进行优化。@MartijnPieters很高兴您阅读此内容。:)否则,这个答案就会产生误导。更新了那句话。请现在检查