浅谈Python中的组包与解包

前言:*args**kwargs是在python的代码中经常用到的两个参数,初学者对这两个参数的理解可能仅仅限于*args是用于接收多余的未命名参数,**kwargs用于接收形参中的命名参数,其中args是一个元组类型,而kwargs是一个字典类型的数据。 其实这两个参数还涉及到了python中的一个重要的知识点,组包与解包。

一、组包

在Python中,组包的操作是自动完成的,将多个值同时赋给一个变量时,解释器会进行自动组包操作。

组包:自动操作,当等号右边有多个数据的时候,会自动包装成为元组。

a = 10, 20, 30
print(a)
# (10, 20, 30)

二、解包

解包就是把一个容器拆开、分解,在Python中的解包是自动完成的。

变量数量 = 元素数量,会进行逐一赋值。

在Python中任何可迭代对象都支持解包,可迭代对象包括列表、元组、字典、集合、字符串、生成器等实现了__next__方法的一切对象。

  1. 解包的意义就是将传递给函数的一个列表,元组,字典,拆分成独立的多个元素然后赋值给函数中的形参变量。
  2. 解包字典有两种解法,一种用*解的只有key,一种用**解的有key、value。但是这个方法**只能在函数定义中使用。

1、表达式

  1. 列表解包
a, b, c = [1, 2, 3]
print(a, b, c)
# 1 2 3
  1. 元祖解包
a, b, c = (1, 2, 3)
print(a, b, c)
# 1 2 3
  1. 字符串解包
a, b, c = "abc"
print(a, b, c)
# a b c
  1. 字典解包
a, b, c = {"a": 1, "b": 2, "c": 3}
print(a, b, c)
# a b c

字典解包后,只会把字典的key取出来,value 则丢掉了。

  1. 多变量赋值
a, b = 1, 2
print(a, b)
# 1 2

以上操作,本质上也是自动解包过程,等号右边其实是一个元组对象 (1, 2),有时候我们代码不小心多了一个逗号 ,,就变成了元组对象。

a = 1,
print(type(a))
print(a)
# <class 'tuple'>
# (1,)

我们在写代码的时候需要特别注意:在 Python 中,交换两个变量非常方便,本质上也是自动解包过程。

a, b = 1, 2
a, b = b, a
print(a, b)
# 2 1
  1. 参数不够的情况
a, b, *c = [1, 2, 3, 4]
print(a, b, c)
# 1 2 [3, 4]

这种语法就是在某个变量面前加一个星号,而且这个星号可以放在任意变量,每个变量都分配一个元素后,剩下的元素都分配给这个带星号的变量。

a, *b, c = [1, 2, 3, 4]
print(a, b, c)
# 1 [2, 3] 4

2、函数

  1. 函数调用

函数调用时,有时你可能会用到两个符号:星号*和 双星号**

def func(a, b, c):
	print(a, b, c)

func(1, 2, 3)
# 1 2 3

func函数定义了三个位置参数 a,b,c,调用该函数必须传入三个参数,除此之外,你也可以传入包含有3个元素的可迭代对象。

func(*[1, 2, 3])
# 1 2 3
func(*(1, 2, 3))
# 1 2 3
func(*"abc")
# a b c
func(*{"a": 1,"b": 2,"c": 3})
# a b c

函数被调用的时候,使用星号*解包一个可迭代对象作为函数的参数。字典对象,可以使用两个星号,解包之后将作为关键字参数传递给函数。

func(**{"a": 1,"b": 2,"c": 3})
# 1 2 3

**符号作用的对象是字典对象,它会自动解包成关键字参数 key=value 的格式:

func(a=1, b=2, c=3)
# 1 2 3
  1. 多解包操作
# 可以使用任意多个解包操作
print(*[1], *[2], 3)
# 1 2 3

于此同时,解包操作除了用在函数调用,还可以作用在表达式中。

*range(4), 4
# (0, 1, 2, 3, 4)
[*range(4), 4]
# [0, 1, 2, 3, 4]
{*range(4), 4}
# {0, 1, 2, 3, 4}
{"x": 1, **{"y": 2}}
# {"x": 1, "y": 2}

可以看出,这种语法使得我们的代码更加优雅了,例如拼接两个列表可以这样:

list1 = [1, 2, 3]
list2 = range(3, 6)
[*list1, *list2]
# [1, 2, 3, 3, 4, 5]

可不可以直接用 + 操作呢?不行,因为 list 类型无法与 range 对象相加,你必须先将 list2 强制转换为 list 对象才能做 +操作。再来看一个例子:如何优雅的合并两个字典

a = {"a": 1, "b": 2}
b = {"c": 3, "d": 4}
{**a, **b}
# {"a": 1, "b": 2, "c": 3, "d": 4}

三、总结

  1. 组包实则是将多个值赋给一个变量,自动组成的是元组。
  2. 自动解包支持一切可迭代对象。
  3. python3中,支持更高级的解包操作,用星号操作使得等号左边的变量个数可以少于右边迭代对象中元素的个数。
  4. 函数调用时,可以用*或者**解包可迭代对象,作为参数传递。
  5. python3.5,函数调用和表达式中可支持更多的解包操作。

猜你喜欢

转载自blog.csdn.net/qq_44034384/article/details/107497530