如何在Python中使用星号表达式解包?


简介

解包的一个基本限制是,你必须预先知道要解包的序列的长度。

如何操作……

random_numbers = [0, 1, 5, 9, 17, 12, 7, 10, 3, 2]
random_numbers_descending = sorted(random_numbers, reverse=True)
print(f"Output \n*** {random_numbers_descending}")

输出

*** [17, 12, 10, 9, 7, 5, 3, 2, 1, 0]

如果我现在想找出这些数字中最大和第二大的数字,我们会得到一个异常“太多值需要解包”。

print(f"Output \n*** Getting the largest and second largest")
largest, second_largest = random_numbers_descending

输出

*** Getting the largest and second largest


---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
in
1 print(f"Output \n*** Getting the largest and second largest")
----> 2 largest, second_largest = random_numbers_descending

ValueError: too many values to unpack (expected 2)

Python经常依赖于索引和切片。例如,如果我想从下面的项目列表中提取最大值和第二大值,我们可以这样做。

largest = random_numbers_descending[0]
print(f"Output \n*** Getting the largest - {largest}")

输出

*** Getting the largest - 17


second_largest = random_numbers_descending[1]
print(f"Output \n*** Getting the second largest - {second_largest}")

输出

*** Getting the second largest - 12


rest_of_numbers = random_numbers_descending[2:]
print(f"Output \n*** Getting the rest of numbers - {rest_of_numbers}")

输出

*** Getting the rest of numbers - [10, 9, 7, 5, 3, 2, 1, 0]

虽然这有效,但所有的索引和切片在视觉上都很冗余。实际上,以这种方式将序列的成员分成不同的子集很容易出错。

为了更好地做到这一点,Python 通过星号表达式支持通配符解包。

这种星号语法允许解包赋值的一部分接收与解包模式的任何其他部分都不匹配的所有值。

largest,second_largest, *rest_of_numbers = random_numbers_descending
print(f"Output \n largest: {largest} \n second_largest:{second_largest} \n rest_of_numbers:{rest_of_numbers}")

输出

largest: 17
second_largest:12
rest_of_numbers:[10, 9, 7, 5, 3, 2, 1, 0]

上面的代码看起来如何?在一行代码中,我们能够更容易地读取并实现输出。星号表达式可以出现在任何位置,因此您可以随时获得通配符解包的好处,只要您需要提取一个切片。

largest: 17
rest_of_numbers:[12, 10, 9, 7, 5, 3, 2, 1]
smallest:0


*rest_of_numbers, second_smallest, smallest = random_numbers_descending
print(f"Output \n rest_of_numbers:{rest_of_numbers} \n second_smallest: {second_smallest} \n smallest:{smallest}")


rest_of_numbers:[17, 12, 10, 9, 7, 5, 3, 2]
second_smallest: 1
smallest:0

但是,要解包包含星号表达式的赋值,您必须至少有一个必需的部分,否则您将得到一个SyntaxError。我们不能单独使用通配符表达式。

*rest_of_numbers = random_numbers_descending


File "", line 1
*rest_of_numbers = random_numbers_descending
^
SyntaxError: starred assignment target must be in a list or tuple

我们也不能在一个单层解包模式中使用多个通配符表达式。这是另一个需要考虑的重要说明。

*rest_of_numbers, *more_smallest, smallest = random_numbers_descending


File "", line 1
*rest_of_numbers, *more_smallest, smallest = random_numbers_descending
^
SyntaxError: two starred expressions in assignment


但是,只要它们是正在解包的多层结构的不同部分的通配符,就可以在一个解包赋值语句中使用多个星号表达式。

player_grandslame_and_atptitles = {
'Federer': (20, 103),
'Nadal': (20,84),}

((player1, (grandslam1, *atptitles1)), (player2, (grandslam2, *atptitles2))) = player_grandslame_and_atptitles.items()

print(f'Output \nPlayer - {player1} Have acheived {grandslam1} grandslams and , {atptitles1} atp tour titles')
print(f'Player - {player2} Have acheived {grandslam2} grandslams and , {atptitles2} atp tour titles')


输出


Player - Federer Have acheived 20 grandslams and , [103] atp tour titles
Player - Nadal Have acheived 20 grandslams and , [84] atp tour titles

星号表达式在所有情况下都成为列表实例。如果要解包的序列中没有剩余的项目,则通配符部分将是一个空列表。当您处理一个预先知道至少有 N 个元素的序列时,这尤其有用。

random_numbers = [0, 1]
first, second, *rest = random_numbers
print(f"Output \n{first, second, rest}")

输出

(0, 1, [])

更新于:2020年11月9日

浏览量 1K+

启动你的职业生涯

通过完成课程获得认证

开始学习
广告