1.6 - 封包解包及其案例解析

发布时间 2024-01-09 18:22:06作者: 虎头小黑

1.6.1 封包和解包

  封包:将多个值赋给同一个变量 或 return返回多个对象 的时候,python会将这多个值封装成一个元组,python的这个特性称之为 封包。

     定义函数的时候,如果使用了 **kwargs 来接收多个自定义关键字参数,在实参调用的时候,会将这些自定义kv实参封装成字典。

# python的封包特性
a = 1,2,3,4
print(type(a))

  

  解包:将一个可迭代对象赋值给多个变量的时候,python会将可迭代对象的元素按照位置依次赋值给对应位置的变量,如果可迭代对象的元素个数大于变量个数,可将 某个变量的前面加上*,这样该变量会接收多余的参数并组成一个列表。python的这个特性称之为 解包。

  1)第一种解包( 可迭代对象赋值 ,可用 * 接收多个值)

# python的解包特性

# 当可迭代对象的长度和变量个数相等的时候,顺序拆分
a, b, c, d = (1,2,3,4)
# 当可迭代对象长度大于变量个数的时候,可在变量前面加上*,作用类似于可变长参数,这样解包的时候会 首先匹配其它位置的元素,然后将剩余元素组成列表,然后赋值给带星号(*)的变量 a,b,*c,d = (1,2,3,4,5) print(c) # [3,4] # 将可迭代对象解包给一个变量,需要后面加上 逗号 *k, = (1,2,3,4) pirnt(k)

  2) 第二种解包 ( 函数传参, )

    2.1)单星号 * 传参 (将 可迭代对象 解包为位置参数,如果可迭代对象为 字典,则单星号 *只会拆包到字典的 key)

# 单星号会将可迭代对象解包为 位置参数
def fun(a, b, c, d):
  return a, b, c, d   # 封包

lst = [1,2,3,4]

# 错误的调用方式
print( type(fun(lst)) )

# 正确的调用方式
print( type(fun(*lst)) )

  在上述案例中,自定义函数fun 需要四个必须参数,lst中虽然有四个元素,但是直接将 lst 传入,实际只占据一个形参的位置,所以会报错。如果将【*可迭代对象名称】格式的参数 *lst 传入,会将可迭代对象lst解包为4个元素,分别赋值给四个形参,所以不会报错。

注:第一种解包方式和第二种解包方式都用 * 的含义区别:第一种解包方式,* 用来将变量接收多个值并生成列表。第二种解包,*表示 在传递实参的时候,将 可迭代对象解包为位置参数。

    2.2)双星号 ** 传参(将 字典 解包为 关键字参数)

# 第二种解包, 函数传参 - 关键字参数
def fun(a,b,c):
  return a,b,c

d = {"a": 1,  "b": 2,  "c": 3}

# fun的正确调用方式
print( type( fun(**d) ) )

 

1.6.2 函数传参案例解析,分析下面两个案例的打印结果

 1 # 函数传参案例一
 2 def fun1(*a): # 在形参中,* 表示 ?
 3     print(a)
 4     print(*a)
 5   
 6 a = (1,2,3)
 7 fun1(*a) # 在实参中,* 表示 解包可迭代对象 变为 位置参数
 8   
 9  
10 # 函数传参案例二
11 def fun2(**a): # 在形参中,** 表示 ?
12    print(a)
13    print(**a)
14  
15 a = {"a" : 1}
16 fun2(**a) # 在实参中,** 表示 解包字典 变为 关键字参数

 

案例解析一:

  3th 定义了一个函数,7th 初始化一个可迭代对象,8th 调用了函数fun1,调用的时候传递实参 *a,会将可迭代对象a解包为位置参数 1 2 3;在自定义函数fun1中,函数头中的*a表示接收不定长参数,因为传过来的是多个实参,多个实参都要传给同一个变量a,因此python会将其封包为一个元组然后赋值a。故 在函数体内,a是一个封包后的元组,因此:在函数体内,4th的输出结果为一个元组:(1,2,3);5th 的输出结果是 将元组解包后的结果 :1 2 3 .

案例解析二:

  13th 定义了一个函数,17th 初始化一个字典, 18th 调用了函数fun2,调用的时候传递实参 **a ,  会将字典a解包为 关键字参数;因此,18th 等效于调用 fun2(a=2)。现在分析 13th:**a 接收自定义命名的关键字参数,并存储为一个字典。因此:14th的输出:{“a”: 1};对于 15th:调用了print()函数,函数在调用的时候,实参 **a 会将 字典a 解包为调用函数的关键字参数,但是print()函数并没有 参数名为a 的参数,因此,程序执行到这一样的时候会报错!!