程序员肖邦的博客 享受编程和技术所带来的快乐

Python基础操作之解包unpacking

2018-11-02
肖邦

本文介绍了 Python 的基础操作:解包(unpacking),这个知识点虽然看起来很简单,但起到简化代码的作用,且为函数调用时参数传递、列表和字典的合并提供了另一种优雅的方式。

解包的英文里叫做 unpacking,就是将容器或集合里的元素逐个取出来放在其它地方,这个过程就是解包。如下:

>>> a, b, c = [1, 2, 3]
>>> a
1
>>> b
2
>>> c
3

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

常见的解包操作

  • 元组解包:
      >>> a, b, c = (1, 2, 3)
    
  • 字符串解包:
      >>> a, b, c = '123'
    
  • 字典解包:
      >>> a, b, c = {'a':1, 'b':2, 'c':3}
      >>> a
      'a'
      >>> b
      'b'
      >>> c
      'c'
    

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

  • 多变量赋值操作(元组解包)
      a, b = 1, 2
    

    本质上也是自动解包的过程,等号右边其实是一个元组对象 (1, 2),有时我们代码中不小心多了一个逗号,就变成了元组对象。在 Python 中交换两个变量非常方便,本质上也是自动解包过程。

    a, b = 1, 2
    a, b = b, a
    

迭代对象元素与变量数量不一致

如果在解包的过程中,遇到左边变量个数小于右边可迭代对象中元素的个数时该怎么办? 在 Python2 中,如果等号左边变量的个数不等于右边可迭代对象中元素的个数,是不允许解包的。但在 Python3 可以这么做。

>>> a, b, *c = [1, 2, 3, 4]
>>> c
[3, 4]
>>> a, *b, c = [1, 2, 3, 4]
# 这个星号可以放在任意变量
# 每个变量都分配一个元素,剩余的元素都分配给这个带星号的变量

这种方式可以使得你的代码写起来更简洁,比如上边例子,在 Python2 中该如何操作呢?

n = [1, 2, 3, 4]
a, b, c = n[0], n[1:-1], n[-1]

函数调用时的解包操作

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

>>> def func(a, b, c):
...     print(a, b, c)
>>> 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 的格式。

在 Python 3.5+ 版本支持在函数调用时,支持有任意个解包操作,而在 Python3.5 之前版本一个函数调用只允许一个解包操作。

print(*[1], *[2], 3)

列表和字典的合并操作

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

>>> *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 = ['a', 'b', 'c']
      list3 = [*list1, *list2]
    
  • 优雅合并两个字典:
      >>> a = {"a":1, "b":2}
      >>> b = {"c":3, "d":4}
      >>> {**a, **b}
      {'a': 1, 'b': 2, 'c': 3, 'd': 4}
    

最后的总结如下:

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

Comments

Content