Python 进阶 - 元组解包

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) #  1
	print(type(b), b) #  1

而这种方式,就是普通的变量赋值,等号左侧没有逗号,要和上面的形式区分开

	a1 = (1, )
	b1 = [1, ]
	print(type(a1), a1) #  (1,)
	print(type(b1), b1) #  [1]

5. 带 * 号的解包

我在上面说到,右边可迭代对象中的元素个数要和左边的保持一致。但是这是python2中的特性,在python3 中通过增加 * 来表示任意数量的,从而实现更简洁的解包方式。如下:

【注意】

  1. *号可以放在左侧的任意位置,但位置不一样,赋值结果也不同
  2. 先给非星号的变量赋值,剩下的元素转换成 list 给*号的变量赋值
  3. * 号不能在一个赋值语句中同时出现两次或者两次以上
  4. 解包字典,是以元组的形式来保存键值对,但解包出来不一定是顺序的
  5. 对于这种单纯的等号赋值的语句,左侧是没有 ** 号这种形式的
	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循环进行拼接的冗余代码!本质上 解包 的底层操作就是遍历右侧对象,依次取出来赋值给左侧变量。

【注意】

  1. Python3.5之前是不允许带有两个或两个以上的*号的!!之后是允许的
  2. 列表/元组在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. 函数中的解包是在 传递参数 的时候加 * 号,而可变参数是在 函数定义 的时候加 * 号
  2. 字典同1所述,只不过把 * 号变成了 ** 号
  3. 当函数传递多个带*号的参数时,会类似于表达式中一样,先自动拼接起来,然后再传参
	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解包的所有操作,如果有需要增加的,或者哪里不对的地方,欢迎留言~

你可能感兴趣的:(Python,#,Python进阶,python)