python中一切可迭代对象都支持解包 - Iterable Unpacking

python封包

当多个元素赋值给一个变量时,python会自动将这些值封装成元组,这个特性称之为封包

a = 1, True, ['a', 'b'], {'age': 18}
print(a, type(a))
# (1, True, ['a', 'b'], {'age': 18}) 

当某个函数返回多个数值时,也会进行封包操作

def tP():
    return 'a', 'b', 666
b = tP()
print(b, type(b))
# ('a', 'b', 666) 

python解包 - Unpack

Function calls are proposed to support an arbitrary number of unpackings rather than just one:

>>> print(*[1], *[2], 3)
1 2 3
>>> dict(**{'x': 1}, y=2, **{'z': 3})
{'x': 1, 'y': 2, 'z': 3}

Unpacking is proposed to be allowed inside tuple, list, set, and dictionary displays:

>>> *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}

In dictionaries, later values will always override earlier ones:

>>> {'x': 1, **{'x': 2}}
{'x': 2}

>>> {**{'x': 2}, 'x': 1}
{'x': 1}

将一个包含多个元素的序列中的元素赋值给多个变量,例如 list ,每个元素当成一个个个体剥离出来,这个过程就是解包

  • 列表解包,将list中每个元素赋值给某一个变量

>>> a, b, c = ['alex', 'andy', 'lucy']
>>> a
'alex'
>>> b
'andy'
>>> c
'lucy'

只要对象是可迭代的,就可以解包操作,可迭代对象包括元组、字典、集合、字符串、生成器等

  • 元组解包
>>> a,b,c = (1, True, ['alex','andy'])
>>> a
1
>>> b
True
>>> c
['alex', 'andy']
  • 字符串解包
>>> a, b, c ,d = "alex"
>>> a
'a'
>>> b
'l'
>>> c
'e'
>>> d
'x'
  • 字典解包

序列解包用于字典时, 默认是对 ’ 键 ’ 进行操作;如果需要对 ’键值对‘ 操作, 则需要使用 items();如果需要对 ’ 值 ’ 进行操作, 则需要使用 values()

1、序列解包用于字典时, 默认是对 ’ 键 ’ 进行操作

>>> a,b,c = {"name": "alex", "age":18, "hobby": "man"}
>>> a
'name'
>>> b
'age'
>>> c
'hobby'
>>> a,b,c    # 可以看到,只能拿到 key 值,value 则丢掉了
('name', 'age', 'hobby')

2、如果需要对 ’键值对‘ 操作, 则需要使用 items()

>>> for key,value in my_dict.items():
...     print(key,value)
...
name alex
age 18
hobby man

3、 如果需要对 ’ 值 ’ 进行操作, 则需要使用 values()

>>> for value in my_dict.values():
...     print(value)
...
alex
18
man
  • 生成器解包

>>> a, b, c = (x + 10 for x in range(3))
>>> a
10
>>> b
11
>>> c
12

注意:用来接收的变量必须与元素数目保持一致,否则会报错~

>>> a ,b, c = 1,2,3,4,5
Traceback (most recent call last):
  File "", line 1, in <module>
ValueError: too many values to unpack (expected 3)

那这种情况怎么解决呢?? 引入参数 ‘*’ 与 ‘* *’

解包之星号 * 的使用

如果可迭代对象包含的元素和前面待赋值变量数量不一致,则会报错。但是可以通过 * 来表示多个元素

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

详细参见官方文档 pep-3132

  • 一个星 *
    在某个变量面前加一个星号,而且这个星号可以放在任意变量,每个变量都分配一个元素后,剩下的元素都分配给这个带星号的变量
>>> a, b, *c = [1,2,3,4,5]
>>> a
1
>>> b
2
>>> c
[3, 4, 5]

这种做法 确实 很飒!! 在python2 中还得通过 列表切片来实现

>>> num = [1,2,3,4,5]
>>> a,b,c = num[0],num[1],num[2:]
>>> a
1
>>> b
2
>>> c
[3, 4, 5]
  • 两个星 ** ,Python 3.x 3.5及以后
    打开字典包 使用两个相邻的星 (pep-0448)
>>> tail = {'y': 2, 'z': 3}
>>> {'x': 1, **tail}
 # {'x': 1, 'y': 2, 'z': 3}

如何优雅的合并两个字典??

巧妙的利用**解包技术,可以简单方便的将两个字典合并到一个新字典中

>>> dict1 = {"name": "alex"}
>>> dict2 = {"age": 18}
>>> dict3 = {**dict1, **dict2}
>>> dict3
{'name': 'alex', 'age': 18}
>>>

https://foofish.net/python-unpacking.html
https://zhuanlan.zhihu.com/p/33896402
https://www.python.org/dev/peps/pep-0448/

_ 的使用

用 _ 表示一些用不到的某些元素,这种表达方式言简意赅、代码易读性高

>>> q, *_ =  [1,2,3]
>>> q
1

>>> q, _, _ = [1,2,3]
>>> q
1
>>> q, *_ ,p=  [1,2,3,4,5]
>>> q
1
>>> p
5
>>> *_, r = [1,2,3,4,5]
>>> r
5
>>>
>>> person = ('alex' , 18, 'man', (7, 26, 2020))
>>> name, *_, (*_, year) = person
>>> name
'alex'
>>> year
2020
>>>

你可能感兴趣的:(Python)