1. 定义
什么是元组解包?元组解包也叫‘元组拆包’,‘迭代对象解包’ 等。也就是把批量的数据进行批量的赋值。当然不只是tuple,任何可迭代对象都支持解包,还包括dict、set、string等一切实现了__next__方法的可迭代对象。
2.??普通示例
下面的是很经典且普通的示例,(Python2中) 右边可迭代对象中的元素个数要和左边的保持一致,否则会报错!
a1, b1, c1 = (1, 2, 3)
print(a1, b1, c1) # 1 2 3
a2, b2, c2 = [1, 2, 3]
print(a2, b2, c2) # 1 2 3
a3, b3, c3 = {'a': 123, 'b': 37, 'c': 34}.items()
print(a3, b3, c3) # ('a', 123) ('b', 37) ('c', 34)
a4, b4, c4 = {'a': 123, 'b': 37, 'c': 34}.keys()
print(a4, b4, c4) # a b c
a5, b5, c5 = {'a': 123, 'b': 37, 'c': 34}.values()
print(a5, b5, c5) # 123 37 34
a6, b6, c6 = 'hel'
print(a6, b6, c6) # h e l
3. 多变量赋值
多变量赋值和交换其实也是元组解包的一种,对于下面的操作:
x, y = 1, 2
实质上上述操作是这样的:首先创建了一个1,2这个元组,然后遍历这个元组,将拿到的两个值按分别赋值给x 和 y。也就是说下面的这些写法都是等价的:
x, y = 1, 2
x, y = (1, 2)
(x, y) = 1, 2
(x, y) = (1, 2)
?4. 单元素解包
单元素解包也就是序列中只有一个元素的解包过程,虽然可能不常用,但是我们一定要知道!
如下的这种方式,在左侧一定要加逗号,那么左边的变量才为右侧元组或者列表解包的结果
a, = (1, )
b, = [1, ]
print(type(a), a) # <class 'int'> 1
print(type(b), b) # <class 'int'> 1
而这种方式,就是普通的变量赋值,等号左侧没有逗号,要和上面的形式区分开
a1 = (1, )
b1 = [1, ]
print(type(a1), a1) # <class 'tuple'> (1,)
print(type(b1), b1) # <class 'list'> [1]
5. 带 * 号的解包
我在上面说到,右边可迭代对象中的元素个数要和左边的保持一致。但是这是python2中的特性,在python3 中通过增加 * 来表示任意数量的,从而实现更简洁的解包方式。如下:
【注意】
- *号可以放在左侧的任意位置,但位置不一样,赋值结果也不同
- 先给非星号的变量赋值,剩下的元素转换成 list 给*号的变量赋值
- * 号不能在一个赋值语句中同时出现两次或者两次以上
- 解包字典,是以元组的形式来保存键值对,但解包出来不一定是顺序的
- 对于这种单纯的等号赋值的语句,左侧是没有 ** 号这种形式的
a, b, *c = (1, 2, 3, 4, 5, 6) # tuple
print(a, b, c) # 1, 2, [3, 4, 5, 6]
a1, b1, *c1 = [1, 2, 3, 4, 5, 6] # list
print(a1, b1, c1) # 1 2 [3, 4, 5, 6]
a2, b2, *c2 = range(1, 7) # range
print(a2, b2, c2) # 1 2 [3, 4, 5, 6]
a3, b3, *c3 = 'hello' # string
print(a3, b3, c3) # h e ['l', 'l', 'o']
a4, b4, *c4 = {'a': 1, 'b': 2, 'c': 3, 'd': 4}.items() # dict
print(a4, b4, c4)
# ('a', 1) ('b', 2) [('c', 3), ('d', 4)] 以元组形式保存键值对
a5, *b5, c5 = [1, 2, 3, 4, 5, 6] # 任意位置的 * 号
print(a5, b5, c5) # 1 [2, 3, 4, 5] 6
6. 表达式中的解包
表达式中应用解包,可以完成列表(元组、字典)等可迭代对象的拼接操作,避免了应用for循环进行拼接的冗余代码!本质上 解包 的底层操作就是遍历右侧对象,依次取出来赋值给左侧变量。
【注意】
- Python3.5之前是不允许带有两个或两个以上的*号的!!之后是允许的
- 列表/元组在python表达式中解包用* 号,字典用 ** 号?
# 列表 / 元组 在python表达式中的操作
nums = [1, 2, 3]
nums1 = [2, 3, 4]
total = [*nums, *nums1] # [1, 2, 3, 2, 3, 4]
total1 = [*nums, 3, 4] # [1, 2, 3, 3, 4]
total2 = [1, *nums, 4] # [1, 1, 2, 3, 4]
a = (1, 3, 4)
b = (3, 3, 4)
c = [*a, *b] # [1, 3, 4, 3, 3, 4]
d = (*a, *b) # (1, 3, 4, 3, 3, 4)
# 字典 在python表达式中的操作
dict1 = {"a": 1, 'b': 2, 'c': 4}
dict2 = {**dict1, 'd': 9} # {'a': 1, 'b': 2, 'c': 4, 'd': 9}
7.? 函数中的解包
【注意】:
- 函数中的解包是在?传递参数?的时候加 * 号,而可变参数是在 函数定义 的时候加 * 号
- 字典同1所述,只不过把 * 号变成了 ** 号
- 当函数传递多个带*号的参数时,会类似于表达式中一样,先自动拼接起来,然后再传参
def show(*args):
print(args)
def dict(**kwargs):
print(kwargs)
nums = [1, 2, 3]
nums1 = [1, 2, 3]
dict1 = {'a': 1, 'b': 2, 'c': 3}
dict2 = {'d': 9}
show(*nums) # (1, 2, 3)
show(*nums, *nums1) # (1, 2, 3, 1, 2, 3)
dict(**dict1) # {'a': 1, 'b': 2, 'c': 3}
dict(**dict1, **dict2) # {'a': 1, 'b': 2, 'c': 3, 'd': 9}
8.?深度解包
在前面的解包操作都是?浅度?的,因为它只进行了一层的解包,接下来我将展示深度解包操作:
其实也很好理解,按照右侧的模式,左侧再来一个一样的变量接着就行
a, (b1, b2, b3), c = (1, (2, 3, 3), 5)
print(a, b1, b2, b3, c) # 1 2 3 3 5
d, f, (e1, e2, e3) = 1, 5, (2, 3, 3)
print(d, f, e1, e2, e3) # 1 5 2 3 3
上面的总结,基本上涵盖了python解包的所有操作,如果有需要增加的,或者哪里不对的地方,欢迎留言~
|