解包 Iterables

Python 3.x >= 3.0

在 Python 3 中,你可以在不知道其中的项的确切数量的情况下解压缩迭代,甚至可以使用变量保存可迭代的末尾。为此,你提供可以收集值列表的变量。这是通过在名称前放置一个星号来完成的。例如,解压缩 list

first, second, *tail, last = [1, 2, 3, 4, 5]
print(first)
# Out: 1
print(second)
# Out: 2
print(tail)
# Out: [3, 4]
print(last)
# Out: 5

注意 :使用*variable 语法时,variable 将始终是一个列表,即使原始类型不是列表。它可能包含零个或多个元素,具体取决于原始列表中的元素数量。

first, second, *tail, last = [1, 2, 3, 4]
print(tail)
# Out: [3]

first, second, *tail, last = [1, 2, 3]
print(tail)
# Out: []
print(last)
# Out: 3

同样,打开 str

begin, *tail = "Hello"
print(begin)
# Out: 'H'
print(tail)
# Out: ['e', 'l', 'l', 'o']

拆包 date 的例子; _ 在这个例子中用作一次性变量(我们只对 year 值感兴趣):

person = ('John', 'Doe', (10, 16, 2016))
*_, (*_, year_of_birth) = person
print(year_of_birth)
# Out: 2016

值得一提的是,由于*会占用不同数量的项目,因此在一项任务中你不能拥有两个*s 用于相同的迭代 - 它不会知道第一次解包中有多少元素,第二次解包中有多少元素:

*head, *tail = [1, 2]
# Out: SyntaxError: two starred expressions in assignment

Python 3.x >= 3.5

到目前为止,我们已经讨论了在分配中拆包。*** 在 Python 3.5 中得到了扩展 。现在可以在一个表达式中进行多次解包操作:

{*range(4), 4, *(5, 6, 7)}
# Out: {0, 1, 2, 3, 4, 5, 6, 7}

Python 2.x >= 2.0

也可以将 iterable 解包为函数参数:

iterable = [1, 2, 3, 4, 5]
print(iterable)
# Out: [1, 2, 3, 4, 5]
print(*iterable)
# Out: 1 2 3 4 5

Python 3.x >= 3.5

打开字典包使用两个相邻的星星**PEP 448 ):

tail = {'y': 2, 'z': 3}
{'x': 1, **tail}
 # Out: {'x': 1, 'y': 2, 'z': 3}

这允许重写旧值和合并字典。

dict1 = {'x': 1, 'y': 1}
dict2 = {'y': 2, 'z': 3}
{**dict1, **dict2}
# Out: {'x': 1, 'y': 2, 'z': 3}

Python 3.x >= 3.0

Python 3 删除了函数中的元组解包。因此,以下内容在 Python 3 中不起作用

# Works in Python 2, but syntax error in Python 3:
map(lambda (x, y): x + y, zip(range(5), range(5)))
# Same is true for non-lambdas:
def example((x, y)):
    pass

# Works in both Python 2 and Python 3:
map(lambda x: x[0] + x[1], zip(range(5), range(5)))
# And non-lambdas, too:
def working_example(x_y):
    x, y = x_y
    pass

有关详细的基本原理,请参见 PEP 3113