Python 装包与拆包
Python 装包与拆包
2024年5月17日
摘要
在各种场景下的程序开发中,都时常会用到集合变量与普通变量之间的交互,有时会需要将集合变量拆散,有时会需要将一些变量装入一个集合。Python 在语法层面提供了非常方便的设计用来拆包和装包。本文将对其进行介绍。
Tuple 自动拆装包
Python 支持对元祖的自动拆包与装包,在以下场景中,只支持一个对象的操作,当出现多个变量与之对应时,将会自动装包,将多个变量生成一个 Tuple:
- 函数返回值
- 对象赋值
例如:
def func():
return 1, 2, 3, 4
result = func()
# (1, 2, 3, 4)
此时,返回值的多个变量就被自动打包成了一个单一的 Tuple 对象传出。
赋值操作也是:
m = 1, 2, 3, 4
print(m)
# (1, 2, 3, 4)
a, b, c, d = m
print(a, b, c, d)
# 1 2 3 4
a, b = b, a
print(a, b)
# 2 1
总而言之,但凡赋值操作的任何一边有超过一个变量,都会被自动打包成 Tuple。
面对不同类型的 集合变量,都可以自动拆包:
a, b, c = (1, 2, 3)
# 1, 2, 3
a, b, c = [1, 2, 3]
# 1, 2, 3
a, b, c = {'x': 1, 'y': 2, 'z': 3}
# 'x', 'y', 'z'
对 Tuple 和 List 拆包都很直观,对 Dict 的拆包只保留 Keys。
*
拆包符号
这个部分我个人并不是很欣赏,因为很多规则都是语法层面的硬定义,并没有什么特别好的形象理解方法,只能做一个罗列了。
函数参数
在函数传入参数的定义上,可以使用 *args
来让 args
捕获多个输入参数,args
本身会以 Tuple 的形式存储。
def func_1(*args):
print(args)
print(*args)
func_1(1, 2, 3, 4, 5, 6)
# (1, 2, 3, 4, 5, 6)
# 1 2 3 4 5 6
def func_2(x, *args):
print(x)
print(args)
print(*args)
func_2(1, 2, 3, 4, 5, 6, 7)
# 1
# (2, 3, 4, 5, 6, 7)
# 2 3 4 5 6 7
def func_3(x, *args, y):
print(x)
print(args)
print(*args)
func_3(1, 2, 3, 4, 5, 6, y=7)
# 1
# (2, 3, 4, 5, 6)
# 2 3 4 5 6
其中,func_1
和 func_2
都比较易懂,需要注意的是 func_3
,*
形式的拆包只能作为最后一个位置参数(Position Parameter),后面的就必须是带名字的关键字参数了(Keyword Parameter)。
变量赋值
在变量赋值上,语法规则就略有不同,但也是能够吸收多个变量,生成一个 List,而不是 Tuple:
a, *xs, b = 1, 2, 3, 4, 5, 6, 7
# a = 1
# xs = [2, 3, 4, 5, 6]
# b = 7
*ys = 1, 2, 3
# SyntaxError: starred assignment target must be in a list or tuple
此时,*
表达式可以不是最后一个元素,但不能是唯一一个元素,否则是一个语法错误。
至于为什么变量赋值的规则和函数参数不同,这真是单纯的语法规则。。
**
拆包符号
这个符号只对 Dict 有效,且至用于函数传参:
def func(a, b, c):
print(a, b, c)
dict = {'a': 1, 'c': 3, 'b': 2}
func(**dict)
# 1 2 3
**
符号将把 dict
拆成 key_1=value_1, key_2=value_2, ...
的形式传入函数,由于都是关键字参数,所以位置不重要。
或是直接把函数参数定义为:
def func(**kwargs):
print(kwargs)
dict = {'a': 1, 'b': 2, 'c': 3}
func(**dict)
# {'a': 1, 'b': 2, 'c': 3}
func(a=1, b=2, c=3)
# {'a': 1, 'b': 2, 'c': 3}
也可以混合使用:
def func(x, *args, **kwargs):
print(x)
print(args)
print(kwargs)
list = [1, 2, 3]
dict = {'a': 4, 'b': 5, 'c': 6}
func(0, *list, **dict)
# 0
# (1, 2, 3)
# {'a': 4, 'b': 5, 'c': 6}