我正在阅读一些旧代码,试图了解它的作用,并且遇到了这个奇怪的陈述:
*x ,= p
p
在这种情况下是一个列表。我一直在努力弄清楚该语句的作用。据我所知,它只是设置x
为的值p
。例如:
p = [1,2]
*x ,= p
print(x)
只是给
[1, 2]
那么这有什么不同x = p
吗?知道这个语法在做什么吗?
我正在阅读一些旧代码,试图了解它的作用,并且遇到了这个奇怪的陈述:
*x ,= p
p
在这种情况下是一个列表。我一直在努力弄清楚该语句的作用。据我所知,它只是设置x
为的值p
。例如:
p = [1,2]
*x ,= p
print(x)
只是给
[1, 2]
那么这有什么不同x = p
吗?知道这个语法在做什么吗?
Answers:
*x ,= p
基本上是x = list(p)
使用扩展的可迭代解压缩的混淆版本。x
为了使分配目标成为元组,必须使用逗号后的逗号(尽管它也可以是列表)。
*x, = p
是从不同的x = p
,因为前者创建一个副本的p
(即一个新的列表),而后者将创建一个参考到原始列表。为了显示:
>>> p = [1, 2]
>>> *x, = p
>>> x == p
True
>>> x is p
False
>>> x = p
>>> x == p
True
>>> x is p
True
*x
,因为加星标的赋值必须在列表或元组中。因此,编写该语句的更明确的方法是(*x,) = p
p
是任何可迭代。
x[0] = 3; p #=> [1, 2]
的上半年x[0] = 3; p #=> [3, 2]
到第二,说明为什么is
和==
是不同的
这是Python 3.0(PEP 3132)中引入的功能。在Python 2中,您可以执行以下操作:
>>> p = [1, 2, 3]
>>> q, r, s = p
>>> q
1
>>> r
2
>>> s
3
Python 3对此进行了扩展,以便一个变量可以包含多个值:
>>> p = [1, 2, 3]
>>> q, *r = p
>>> q
1
>>> r
[2, 3]
因此,这就是这里所使用的。但是,它不是两个变量来保存三个值,而是仅一个变量来获取列表中的每个值。这是从不同的x = p
,因为x = p
仅仅意味着x
是另一个名字p
。但是,在这种情况下,它是一个新列表,恰好具有相同的值。(您可能对“最少惊讶”和可变默认参数感兴趣)
产生此效果的其他两种常见方法是:
>>> x = list(p)
和
>>> x = p[:]
从Python 3.3开始,list对象实际上具有用于复制的方法:
x = p.copy()
切片实际上是一个非常相似的概念。正如nneonneo指出的那样,这仅适用于支持切片的列表和元组之类的对象。但是,您提到的方法适用于任何可迭代的方法:字典,集合,生成器等。
x = p[:]
要求它p
是可切片的。这不包括发电机。
PEP 3132 was accepted
。另外,PEP本身说Python版本是3.0。我很确定那是必须的。
.copy
方法。
您应该始终将这些扔给您dis
,看看它会把什么扔回到您身上;您会看到与以下*x, = p
内容实际上有何不同x = p
:
dis('*x, = p')
1 0 LOAD_NAME 0 (p)
2 UNPACK_EX 0
4 STORE_NAME 1 (x)
而,简单的赋值语句:
dis('x = p')
1 0 LOAD_NAME 0 (p)
2 STORE_NAME 1 (x)
(剥离无关的None
回报)
如您所见UNPACK_EX
,它们之间是不同的操作码。它记录为:
实现带有加星标目标的分配:将TOS(堆栈顶部)中的可迭代项解压缩为单个值,其中值的总数可以小于可迭代项中的项数:新值之一将是所有值的列表剩余物品。
正如Eugene所指出的,这就是为什么您会得到一个新对象,该对象被名称x
引用,而不是对已经存在的对象的引用(与一样x = p
)。
*x,
确实看起来很奇怪(所有地方都有多余的逗号),但这是必需的。左侧必须是一个元组或一个列表,并且由于在Python中创建单个元素元组的古怪性,您需要使用结尾,
:
i = 1, # one element tuple
如果您喜欢使人困惑,则可以始终使用以下list
版本:
[*x] = p
它做的完全一样,但是没有多余的逗号在那儿。
您可以从下面的示例中清楚地了解它
L = [1, 2, 3, 4]
while L:
temp, *L = L
print(temp, L)
它的作用是,front变量每次都会获得第一项,其余列表将被赋予L。
输出将如下所示。
1 [2, 3, 4]
2 [3, 4]
3 [4]
4 []
还看下面的例子
x, *y, z = "python"
print(x,y,z)
在这两个x,z中,将从字符串中获得每个字母,这意味着第一个字母被分配给x,最后一个字母将被分配给z,其余的字符串将被分配给变量y。
p ['y', 't', 'h', 'o'] n
再举一个例子
a, b, *c = [0,1,2,3]
print(a,b,c)
0 1 [2,3]
边界情况:如果star变量没有剩余,那么它将得到一个空列表。
例:
a,b=[1]
print(a,b)
1 []