2. 普通示例什么是元组解包?元组解包也叫‘元组拆包’,‘迭代对象解包’ 等。也就是把批量的数据进行批量的赋值。当然不只是tuple,任何可迭代对象都支持解包,还包括dict、set、string等一切实现了__next__方法的可迭代对象。
下面的是很经典且普通的示例,(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 l3. 多变量赋值
多变量赋值和交换其实也是元组解包的一种,对于下面的操作:
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) #1 print(type(b), b) # 1
而这种方式,就是普通的变量赋值,等号左侧没有逗号,要和上面的形式区分开
a1 = (1, ) b1 = [1, ] print(type(a1), a1) #5. 带 * 号的解包(1,) print(type(b1), b1) # [1]
我在上面说到,右边可迭代对象中的元素个数要和左边的保持一致。但是这是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] 66. 表达式中的解包
表达式中应用解包,可以完成列表(元组、字典)等可迭代对象的拼接操作,避免了应用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解包的所有操作,如果有需要增加的,或者哪里不对的地方,欢迎留言~