理解* x,= lst

时间:2017-04-03 17:39:47

标签: python python-3.x iterable-unpacking

我正在阅读一些旧代码,试图了解它的作用,我偶然发现了这个奇怪的声明:

*x ,= p

p是此上下文中的列表。我一直试图找出这句话的作用。据我所知,它只是将x设置为p的值。例如:

p = [1,2]
*x ,= p    
print(x)

刚刚给出

[1, 2]

这与x = p有什么不同?知道这个语法在做什么吗?

4 个答案:

答案 0 :(得分:72)

*x ,= p基本上是使用extended iterable unpackingx = 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

答案 1 :(得分:44)

它是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仅表示xp的另一个名称。但是,在这种情况下,它是一个新列表,恰好在其中具有相同的值。 (您可能对"Least Astonishment" and the Mutable Default Argument

感兴趣

产生这种效果的另外两种常见方法是:

>>> x = list(p)

>>> x = p[:]

从Python 3.3开始,list对象实际上有一个用于复制的方法:

x = p.copy()

切片实际上是一个非常相似的概念。然而,正如nneonneo指出的那样,它仅适用于支持切片的列表和元组等对象。但是,您提到的方法适用于任何可迭代的:字典,集合,生成器等。

答案 2 :(得分:14)

你应该总是把这些扔到dis,看看它会给你什么;您会看到*x, = px = 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是这些之间的不同操作码; it's documented as

  

使用已加星标的目标实现赋值:将TOS(堆栈顶部)中的iterable解包为单个值,其中值的总数可以小于iterable中的项数:其中一个新值将是所有剩余物品的清单。

正如Eugene所说,这就是为什么你得到一个名为x的新对象,而不是对已存在对象的引用(如x = p的情况)。

*x,看起来很奇怪(那里有额外的逗号和所有)但这里需要它。左侧必须是元组或列表,并且由于在Python中创建单个元素元组的怪癖,您需要使用尾随,

i = 1, # one element tuple

如果您喜欢令人困惑的人,您可以随时使用list版本:

[*x] = p

完全相同,但没有那个额外的逗号挂在那里。

答案 3 :(得分:0)

您可以从下面的示例中清楚地了解它

L = [1, 2, 3, 4]
while L:
    temp, *L = L             
    print(temp, L)

它的作用是,前面的变量每次都会获得第一项,其余的列表将被赋予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 []