前言

1、解包在英文里叫做 Unpacking,就是将容器里面的元素逐个取出来(防杠精:此处描述并不严谨,因为容器中的元素并没有发生改变)放在其它地方。

2、举例:

详解python解包_python

如果列表中有3个元素,那么刚好可以分配给3个变量。

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

3、

1、概念

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

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

2、注意

(1)自动解包支持一切可迭代对象

(2)python3中,支持更高级的解包操作,用星号操作使得等号左边的变量个数可以少于右边迭代对象中元素的个数。

(3)函数调用时,可以用*或者**解包可迭代对象,作为参数传递。

(4)python3.5,函数调用和表达式中可支持更多的解包操作。

3、实例

一个list是一个整体,想把list中每个元素当成个体剥离出来。

>>> name, age, date = ['Bob', 20, '2018-1-1']

>>> name

'Bob'

>>> age

20

>>> date

'2018-1-1'

2.可迭代对象都可以这样做



# 列表

>>> a,b,c = ['a', 'b', 'c']

>>> a

'a'



>>> a,b,c = enumerate(['a', 'b', 'c'])

>>> a

(0, 'a')





# 元组

>>> a,b,c = ('a', 'b', 'c')

>>> a

'a'



# 字典

>>> a,b,c = {'a':1, 'b':2, 'c':3}

>>> a

'a'



>>> a,b,c = {'a':1, 'b':2, 'c':3}.items()

>>> a

('a', 1)





# 字符串

>>> a,b,c = 'abc'

>>> a

'a'



# 生成器

>>> a,b,c = (x + 1 for x in range(3))

>>> a

1

元组解包

详解python解包_python_02

字符串解包

详解python解包_python_03 

字典解包

详解python解包_解包_04

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

 

1、你可能见过多变量赋值操作,例如:

详解python解包_python_05

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

详解python解包_python_06

2、在 Python 中,交换两个变量非常方便,本质上也是自动解包过程。

详解python解包_解包_07

3、如果在解包过程中,遇到左边变量个数小于右边可迭代对象中元素的个数时该怎么办? 好比你们家有3口人,你老婆却买了4个苹果,怎么分配呢?

在 Python2 中,如果等号左边变量的个数不等于右边可迭代对象中元素的个数,是不允许解包的。

4、但在 Python3 可以这么做了。这个特性可以在 PEP 3132 中看到。例如下面这块代码:

详解python解包_解包_08

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

详解python解包_迭代_09

5、这种语法有什么好处呢?它使得你的代码写起来更简洁,比如上面例子,在 Python2 中该怎么操作呢?思考3秒钟,再看答案。

详解python解包_迭代_10

6、以上是表达式解包的一些操作,接下来介绍函数调用时的解包操作。函数调用时,有时你可能会用到两个符号:星号*和 双星号**。

详解python解包_迭代_11

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

详解python解包_迭代_12

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

详解python解包_解包_13

看到了吗?和上面例子的区别是多了一个星号,结果完全不一样,原因是什么? 答案是** 符号作用的对象是字典对象,它会自动解包成关键字参数 key=value 的格式:

详解python解包_python_14

如果字典对象中的 key 不是 a,b,c,会出现什么情况?请读者自行测试。

总结一下,一个星号可作用于所有的可迭代对象,称为迭代器解包操作,作为位置参数传递给函数,两个星号只能作用于字典对象,称之为字典解包操作,作为关键字参数传递给函数。使用 *和 ** 的解包的好处是能节省代码量,使得代码看起来更优雅,不然你得这样写:

详解python解包_python_15

到这里,解包还没介绍完,因为 Python3.5,也就是 PEP 448 对解包操作做了进一步扩展, 在 3.5 之前的版本,函数调用时,一个函数中解包操作只允许一个* 和 一个**。从 3.5 开始,在函数调用中,可以有任意多个解包操作,例如:

详解python解包_解包_16

再来看看 python3.5以上版本

详解python解包_python_17

从 3.5 开始可以接受多个解包,于此同时,解包操作除了用在函数调用,还可以作用在表达式中。

详解python解包_迭代_18

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

详解python解包_迭代_19

可不可以直接用 + 操作呢?不行,因为 list 类型无法与 range 对象相加,你必须先将 list2 强制转换为 list 对象才能做 +操作,这个留给读者自行验证。

再来看一个例子:如何优雅的合并两个字典

详解python解包_解包_20

在3.5之前的版本,你不得不写更多的代码:

详解python解包_迭代_21

到此,关于 Python 解包给你介绍完了。

最后总结一下:

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

去期待陌生,去拥抱惊喜。