这个机制的工作方式是组合两个特征 – 形成隐式元组和元组/列表解包。
当你做某事= x,y,Python会做的是隐式地创建一个包含两个元素x和y的tuple(一种不可变的列表)。所以,以下两行代码完全相同:
something = x, y
something = (x, y)
当然,元组可以包含两个以上的元素:
something = a, b, c, d, e
something = (a, b, c, d, e)
此功能的预期用例是使功能更简单/更清晰,从函数返回多个值:
def foo():
return "hello", "world"
第二个功能是元组/列表解包。无论何时在左侧有一系列变量,以及任何类型的列表,元组或其他集合,Python将尝试将右侧的每个元素与左侧的元素相匹配:
>>> a, b, c = [11, 22, 33]
>>> print(a)
11
>>> print(b)
22
>>> print(c)
33
如果它有帮助,行a,b,c = [11,22,33]基本上与做:
temp = [11, 22, 33]
a = temp[0]
b = temp[1]
c = temp[2]
请注意,右侧可以是字面上的任何类型的集合,而不仅仅是元组或列表。所以下列代码是有效的:
>>> p, q = "az"
>>> print(p + " " + q)
a z
>>>
>>> s, t = {'cat': 'foo', 'dog': 'bar'}
>>> print(s + " " + t)
cat dog
(尽管Python中的字典没有义务按照任何特定的顺序进行,并且由于键的顺序可以自由地加密,因此打包它们可能不会有用,因为每次可能会获得不同的结果。 )
如果变量的数量和集合中的元素数量不匹配,Python将抛出异常:
>>> a, b = (1, 2, 3)
Traceback (most recent call last):
File "", line 1, in
ValueError: too many values to unpack (expected 2)
>>> a, b, c = (1, 2)
Traceback (most recent call last):
File "", line 1, in
ValueError: need more than 2 values to unpack
所以这意味着如果我们从上面调用了我们的foo函数,并且执行了以下操作:
>>> x, y = foo()
…变量x将等于字符串“hello”,变量y将等于字符串“world”。
所以最终,这意味着你原来的代码片段:
x = "salil"
y = "Ajay"
y, x = x, y
…在逻辑上等同于以下内容:
x = "salil"
y = "Ajay"
temp = (x, y) # evaluates to ("salil", "Ajay")
y, x = temp
…分解更多,在逻辑上等同于以下内容:
x = "salil"
y = "Ajay"
temp = (x, y) # evaluates to ("salil", "Ajay")
y = temp[0]
x = temp[1]
请注意,您可以认为这两个操作分开进行。首先,元组被形成和评估,然后元组被解包回到变量中。净效应是两个变量的值互换。
(但是,事实证明,CPython解释器(Python的原始和“标准”实现)在此处进行了一些优化:它将优化交换,并且不会执行完整的元组拆包 – 请参阅下面的注释。 “我不知道Python的其他实现方式是否一样,尽管我怀疑他们可能会这样做,但无论如何,这种优化是针对特定于实现的,独立于Python语言本身的设计。