python中的装包与拆包

本文深入探讨Python中*args和**kwargs的使用方法及原理,解析如何利用它们进行参数的打包与解包,帮助读者更好地掌握这两个实用的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

*args和 **kwargs是在python的代码中经常用到的两个参数,初学者对这两个参数的理解可能仅仅限于*args是用于接收多余的未命名参数,**kwargs用于接收形参中的命名参数,其中args是一个元组类型,而kwargs是一个字典类型的数据。 

其实这两个参数还涉及到了python中的一个重要的知识点,拆包与解包。这篇文章将会通过对这两个参数的拆开揉碎讲解,让小伙伴能对拆包解包有一些更深刻的认识。(我一直认为这个世界上只存在懂与不懂两种状态,从来没有什么似懂非懂)。

1.*args
先看下面这段代码,挺住别晕,哈哈。
def run(a,*args):
    #第一个参数传给了a
    print(a)
    # args是一个元组,里面是2和3两个参数
    print(args)
    # *args是将这个元组中的元素依次取出来
    print("对args拆包")
    print(*args) # *args 相当于 a,b = args
    print("将未拆包的数据传给run1")
    run1(args)
    print("将拆包后的数据传给run1")
    run1(*args)

def run1(*args):
    print("输出元组")
    print(args)
    print("对元组进行拆包")
    print(*args)

run(1,2,3) #后面的2和3
下面是上面程序的输出结果:
理解这段代码需要把握住下面几点:
1.形参中的*args其实真正接收数据的args,它是一个元组,把传进来的数据放在了args这个元组中。
2. 函数体里的args依然是那个元组,但是*args的含义就是把元组中的数据进行拆包,也就是把元组中的数据拆成单个数据。
3. 对于args这个元组,如果不对其进行解包,就将其作为实参传给其它以*args作为形参的函数时,args这个元组会看看作一个整体,作为一个类型为元组的数据传入。
把握上面的这三点,就不会被刚才的程序绕晕了。
2. **kwargs
如果对上面的*args理解了,那么这个**kwargs也就不难理解了,把这两个**类比成之前的一个*,接下来程序的所有执行结果都可以得到合理的解释。
def run(**kwargs):#传来的 key = value 类型的实参会映射成kwargs里面的键和值
       # kwargs是一个字典,将未命名参数以键值对的形式
       print(kwargs)
       print("对kwargs拆包")
       #  此处可以把**kwargs理解成对字典进行了拆包,{"a":1,"b":2}的kwargs字典又
       # 被拆成了a=1,b=2传递给run1,但是**kwargs是不能像之前*args那样被打印出来看的
       run1(**kwargs)
       #print(**kwargs)
   def run1(a,b): #此处的参数名一定要和字典的键的名称一致
      print(a,b)

run(a=1,b=2)
执行结果如下图:
总结:
1. *args作为形参时是用来接收多余的未命名参数,而**kwargs是用来接收key=value这种类型的命名参数,args是元组,kwargs是字典。
2. *和**在函数体中除了拆包之外,并没有什么卵用。
3. 装包的含义就是把未命名参数和命名参数分别放在元组或者字典中。

-------------------------

2022年7月17日更新。

几年前写的文章,后面因为个人的一些原因,很惭愧博客没有坚持写下去,偶然回来看评论确实帮助到了很多同学,内心还是有一点高兴,这篇文章说的知识点并不是那些所谓的面试秒杀,高并发等对我们这些大多数日常在公司打螺丝的人来说只有面试时用到的大而虚的东西,但我想当时把这些说明白在今天看来还是有它的意义。我自己几年前也注册过一个公众号,后面没弄下去的原因是自己的知识输入确实无法支撑起持续的输出,渐渐放弃了。最近又重新申请了一个公众号,但是纯打算扯扯蛋,聊聊自己的日常生活、学习理财的体会,关于持续学习以及感兴趣的一些事情,因为纯技术的号我自己也清楚自己搞不动。我自己个人情况大体是:本科:计算机,研究生:人工智能。因为是菜狗,调参实在学不明白,毕业后目前还是在某大厂干开发大头兵,有些刚工作的同学如果需要内推,我很乐意帮忙,毕竟现在确实就业大环境不好。我最近也在思考,如果有一天自己真的被毕业了怎么办?毕竟 heros come and go,but 裁员 forever.  后来想了想一直焦虑也没啥用,保持持续学习,生活上开源节流,认真学习下理财知识,合理安排自己的工资,是自己接下来要做的事情,因为自己真的也没其它能搞钱的特长。大家迷茫时也不要过度焦虑,一起加油。公众号名称:苇小院

   

<think>我们正在讨论Python中的元组打(packing)拆包(unpacking)机制。根据引用内容,我们可以这样理解: 1. **元组打(Tuple Packing)**:当你在一个表达式中用逗号分隔多个值,Python会自动将这些值打成一个元组。例如: ```python t = 1, 2, 3 # 这是一个元组打,t被赋值为(1, 2, 3) ``` 2. **元组拆包(Tuple Unpacking)**:这是将一个元组(或任何可迭代对象)中的元素分别赋值给多个变量的过程。例如: ```python a, b, c = t # 将元组t中的三个元素分别赋值给a, b, c ``` 拆包要求左侧变量的数量必须右侧元组中的元素数量一致,否则会引发`ValueError`。 引用[1]中提到:“多重赋值真的只是元组打序列解包的一个组合。” 例如: ```python a, b = b, a # 交换ab的值 ``` 实际上,右侧`b, a`会被打成一个元组,然后这个元组被拆包赋值给左侧的`a``b`。 引用[2]说明了元组创建的语法:用逗号分隔元素,圆括号是可选的(除了某些特殊情况,比如空元组必须用`()`表示)。 引用[3]则强调了元组的不可变性(immutable),这使得元组可以作为字典的键,而列表则不行。 ### 元组打拆包的详细解释 #### 打是自动进行的,当你用逗号分隔多个值时,这些值就被打成一个元组。 ```python # 打示例 my_tuple = 1, 2, 3 # 等同于 (1,2,3) ``` #### 拆包 拆包可以用于任何可迭代对象(不仅仅是元组)。例如: ```python # 拆包示例 x, y, z = my_tuple # x=1, y=2, z=3 ``` #### 扩展拆包Python 3中,还可以使用星号运算符(`*`)来捕获多个元素,用于当元素数量不确定的情况。例如: ```python # 使用*来捕获多个元素 first, *middle, last = (1,2,3,4,5) # first=1, middle=[2,3,4], last=5 ``` #### 函数参数中的拆包 在函数调用时,可以使用`*`运算符将元组拆包为位置参数,使用`**`将字典拆包为关键字参数。例如: ```python def func(a, b, c): return a + b + c args = (1, 2, 3) result = func(*args) # 相当于 func(1,2,3) ``` ### 示例代码 ```python # 打拆包示例 # 打 point = 3, 5 # 创建元组(3,5) # 拆包 x, y = point print(f"x={x}, y={y}") # 输出: x=3, y=5 # 多重赋值(打拆包的组合) a = 10 b = 20 a, b = b, a # 交换ab的值,先打(b,a)成元组,再拆包赋值给a,b print(f"a={a}, b={b}") # 输出: a=20, b=10 # 使用*进行扩展拆包 numbers = (1, 2, 3, 4, 5) first, *rest, last = numbers print(f"first={first}, rest={rest}, last={last}") # 输出: first=1, rest=[2,3,4], last=5 # 函数参数拆包 def add(a, b, c): return a+b+c triple = (1, 2, 3) print(add(*triple)) # 输出: 6 ``` ### 注意事项 - 拆包时,左侧变量的数量必须右侧可迭代对象中的元素数量一致,否则会引发`ValueError`。 - 使用星号(`*`)可以捕获多个元素,但每个拆包表达式中只能有一个星号变量。 §§相关问题§§ 1. Python中元组列表的主要区别是什么? 2. 为什么元组可以作为字典的键而列表不能? 3. 在Python中,如何利用元组拆包实现函数返回多个值? 4. 扩展拆包(使用`*`)在Python的哪个版本引入?它还有哪些用法?</think>### Python元组打拆包机制详解 在Python中,元组的打(packing)拆包(unpacking)是处理序列数据的核心机制,尤其适用于多重赋值函数返回值处理。 #### 1. **元组打(Tuple Packing)** 当用逗号分隔多个值时,Python会自动将其打为元组: ```python # 打示例 coordinates = 10, 20, 30 # 自动打为元组(10, 20, 30) print(type(coordinates)) # 输出: <class 'tuple'> ``` 引用[2]明确指出:元组可通过逗号分隔元素创建,圆括号是可选的(空元组除外)[^2]。 #### 2. **元组拆包(Tuple Unpacking)** 将元组元素解压赋值给多个变量: ```python # 拆包示例 x, y, z = coordinates # 拆包赋值 print(y) # 输出: 20 ``` 引用[1]强调:拆包要求左侧变量数右侧元素数严格匹配[^1]。 #### 3. **高级应用场景** - **多重赋值**(打+拆包组合): ```python a, b = 5, 10 # 右侧打成元组(5,10),左侧拆包 a, b = b, a # 经典值交换:无需临时变量 ``` - **函数返回多值**: ```python def get_dimensions(): return 1920, 1080 # 隐式打为元组 width, height = get_dimensions() # 调用端拆包 ``` - **带星号(*)的扩展拆包**(Python 3.5+): ```python first, *middle, last = (1, 2, 3, 4, 5) print(middle) # 输出: [2, 3, 4] (*捕获剩余元素为列表) ``` #### 4. **列表的关键差异** 引用[3]说明:元组不可变性使其可作为字典键,而列表不行[^3]: ```python valid_dict = {(1, 2): "坐标"} # 元组为键-合法 invalid_dict = {[1, 2]: "坐标"} # 列表为键-TypeError ``` #### 5. **注意事项** - 拆包数量必须匹配: ```python # 错误示例(引发ValueError) a, b = (1, 2, 3) ``` - 嵌套结构拆包: ```python points = ((1,2), (3,4)) for (x1, y1), (x2, y2) in points: print(f"线段: ({x1},{y1})→({x2},{y2})") ``` ### 代码实践 ```python # 综合示例:坐标转换 def transform_point(x, y): return x+10, y-5 # 打返回新坐标 orig_point = (30, 40) new_x, new_y = transform_point(*orig_point) # 拆包传参+拆包接值 print(f"新坐标: ({new_x}, {new_y})") # 输出: (40, 35) ```
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值