解包在英文里叫做 Unpacking,就是将容器里面的元素逐个取出来(防杠精:此处描述并不严谨,因为容器中的元素并没有发生改变)放在其它地方,好比你老婆去菜市场买了一袋苹果回来分别发给家里的每个成员,这个过程就是解包。Python 中的解包是自动完成的,例如:

  1. >>> a, b, c = [1,2,3]
  2. >>> a
  3. 1
  4. >>> b
  5. 2
  6. >>> c
  7. 3

如果列表中有3个元素,那么刚好可以分配给3个变量。除了列表对象可以解包之外,任何可迭代对象都支持解包,可迭代对象包括元组、字典、集合、字符串、生成器等实现了__next__方法的一切对象。

元组解包

  1. >>> a,b,c = (1,2,3)
  2. >>> a
  3. 1
  4. >>> b
  5. 2
  6. >>> c
  7. 3

字符串解包

  1. >>> a,b,c = "abc"
  2. >>> a
  3. 'a'
  4. >>> b
  5. 'b'
  6. >>> c
  7. 'c'

字典解包

  1. >>> a,b,c = {"a":1, "b":2, "c":3}
  2. >>> a
  3. 'a'
  4. >>> b
  5. 'b'
  6. >>> c
  7. 'c'

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

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

  1. >>> a, b = 1, 2
  2. >>> a
  3. 1
  4. >>> b
  5. 2

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

  1. >>> a = 1,
  2. >>> a
  3. (1,)
  4. ----------
  5. >>> a = 1
  6. >>> a
  7. 1

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

  1. >>> a, b = 1, 2
  2. >>> a, b = b, a
  3. >>> a
  4. 2
  5. >>> b
  6. 1

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

在 Python2 中,如果等号左边变量的个数不等于右边可迭代对象中元素的个数,是不允许解包的。但在 Python3 可以这么做了。这个特性可以在 PEP 3132 中看到。

  1. >>> a, b, *c = [1,2,3,4]
  2. >>> a
  3. 1
  4. >>> b
  5. 2
  6. >>> c
  7. [3, 4]
  8. >>>

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

  1. >>> a, *b, c = [1,2,3,4]
  2. >>> a
  3. 1
  4. >>> b
  5. [2, 3]
  6. >>> c
  7. 4

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

  1. >>> n = [1,2,3,4]
  2. # 使用切片操作
  3. >>> a, b, c = n[0], n[1:-1], n[-1]
  4. >>> a
  5. 1
  6. >>> b
  7. [2, 3]
  8. >>> c
  9. 4

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

  1. >>> def func(a,b,c):
  2. ... print(a,b,c)
  3. ...
  4. >>> func(1,2,3)
  5. 1 2 3

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

  1. >>> func(*[1,2,3])
  2. 1 2 3
  3. >>> func(*(1,2,3))
  4. 1 2 3
  5. >>> func(*"abc")
  6. a b c
  7. >>> func(*{"a":1,"b":2,"c":3})
  8. a b c

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

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

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

  1. >>> func(a=1,b=2,c=3)
  2. 1 2 3

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

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

  1. >>> d = {"a":1, "b":2, "c":3}
  2. >>> func(a = d['a'], b=d['b'], c=d['c'])
  3. 1 2 3
  4. >>>

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

  1. # Python 3.4 中 print 函数 不允许多个 * 操作
  2. >>> print(*[1,2,3], *[3,4])
  3. File "<stdin>", line 1
  4. print(*[1,2,3], *[3,4])
  5. ^
  6. SyntaxError: invalid syntax
  7. >>>

再来看看 python3.5以上版本

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

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

  1. >>> *range(4), 4
  2. (0, 1, 2, 3, 4)
  3. >>> [*range(4), 4]
  4. [0, 1, 2, 3, 4]
  5. >>> {*range(4), 4}
  6. {0, 1, 2, 3, 4}
  7. >>> {'x': 1, **{'y': 2}}
  8. {'x': 1, 'y': 2}

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

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

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

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

  1. >>> a = {"a":1, "b":2}
  2. >>> b = {"c":3, "d":4}
  3. >>> {**a, **b}
  4. {'a': 1, 'b': 2, 'c': 3, 'd': 4}

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

  1. >>> import copy
  2. >>>
  3. >>> c = copy.deepcopy(a)
  4. >>> c.update(b)
  5. >>> c
  6. {'a': 1, 'b': 2, 'c': 3, 'd': 4}

到此,关于 Python 解包给你介绍完了,如果本文对你有收获,请点赞、转发支持。

最后给你总结一下:

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

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

关于Python 解包,你需要知道的一切的更多相关文章

  1. Python解包参数列表及 Lambda 表达式

    解包参数列表 当参数已经在python列表或元组中但需要为需要单独位置参数的函数调用解包时,会发生相反的情况.例如,内置的 range() 函数需要单独的 start 和 stop 参数.如果它们不能 ...

  2. python解包

    概念 python的解包可以这样来理解:把元素给拆分并把其赋值给自己所需要的变量,因此元素应该是一个可迭代对象. 形式 简单版本 下面展示的是解包的基本形式,根据长度赋值给对应多的变量. name_l ...

  3. Python - 解包的各种骚操作

    为什么要讲解包 因为我觉得解包是 Python 的一大特性,大大提升了编程的效率,而且适用性很广 啥是解包 个人通俗理解:解开包袱,拿出东西 正确理解:将元素从可迭代对象中一个个取出来 python ...

  4. python高级特性之封包与解包

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:kwsy PS:如有需要Python学习资料的小伙伴可以加点击下方链接 ...

  5. python 零散记录(五) import的几种方式 序列解包 条件和循环 强调getattr内建函数

    用import关键字导入模块的几种方式: #python是自解释的,不必多说,代码本身就是人可读的 import xxx from xxx import xxx from xxx import xx1 ...

  6. Python中的可变、不可变对象和赋值技巧序列解包

    可变对象和不可变对象 在python中一切皆对象.在Python中不存在所谓的值传递调用,一切传递都是对象的引用,也可认为是传址. python中,对象分为可变(mutable)和不可变(immuta ...

  7. Python 序列与映射的解包操作

    解包就是把序列或映射中每个元素单独提取出来,序列解包的一种简单用法就是把首个或前几个元素与后面几个元素分别提取出来,例如: first, seconde, *rest = sequence 如果seq ...

  8. Python 序列与映射的解包操作-乾颐堂

    解包就是把序列或映射中每个元素单独提取出来,序列解包的一种简单用法就是把首个或前几个元素与后面几个元素分别提取出来,例如: first, seconde, *rest = sequence 如果seq ...

  9. Python小技巧:使用*解包和itertools.product()求笛卡尔积

    [问题] 目前有一字符串s = "['a', 'b'],['c', 'd']",想把它分开成为两个列表: list1 = ['a', 'b'] list2 = ['c', 'd'] ...

随机推荐

  1. DP的优化总结

    一.预备知识 \(tD/eD\) 问题:状态 t 维,决策 e 维.时间复杂度\(O(n^{e+t})\). 四边形不等式: 称代价函数 w 满足凸四边形不等式,当:\(w(a,c)+w(b,d)\l ...

  2. python学习日记(包——package)

    简述——包 包是一种通过使用‘.模块名’来组织python模块名称空间的方式. 注意: 1. 无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都 ...

  3. cucumber学习笔记

    来源于cucumber官网 学习完了之后全部整理一遍

  4. 浅议极大似然估计(MLE)背后的思想原理

    1. 概率思想与归纳思想 0x1:归纳推理思想 所谓归纳推理思想,即是由某类事物的部分对象具有某些特征,推出该类事物的全部对象都具有这些特征的推理.抽象地来说,由个别事实概括出一般结论的推理称为归纳推 ...

  5. D3 learning notes

    D3 https://d3js.org/ 数据驱动文档显示, 利用 SVG HTML CSS技术. D3.js is a JavaScript library for manipulating doc ...

  6. python super参数错误

    # -*- coding:utf-8 _*-"""@author:Administrator@file: yamlparser.py@time: 2018/09/07&q ...

  7. python3 练手实例3 摄氏温度与华氏温度转换

    def wd(): w=input('请输入一个摄氏温度或者一个华氏温度,如,34c/C or 34f/F:') if w[-1] in ['c','C']: w=float(w[:-1]) hs=1 ...

  8. python2x如何迁移代码到python3中

    2to3 - 自动Python 2到3代码转换 2to3是一个Python程序,它读取Python 2.x源代码并应用一系列修复程序将其转换为有效的Python 3.x代码.标准库包含一组丰富的修复程 ...

  9. UOJ #460 新年的拯救计划

    清真的构造题 UOJ# 460 题意 求将$ n$个点的完全图划分成最多的生成树的数量,并输出一种构造方案 题解 首先一棵生成树有$ n-1$条边,而原完全图只有$\frac{n·(n-1)}{2}$ ...

  10. HG奋斗赛A[20190428]

    T1 很简单,判断这个字符串有多少个不同的字符,让后用k减一减 注意: 1.如果不同字符数大于k,不要输出负数 2.变量名别打错 上代码 #include <cstdio> #includ ...