一篇文章彻底搞懂Python魔法参数args和kwargs(通俗易懂)

 更新时间:2025年02月05日 09:04:13   作者:蜘蛛侠在写码  
这篇文章主要介绍了Python中的*args和**kwargs,它们分别是可变位置参数和可变关键字参数,文章通过实际例子展示了如何在函数、装饰器等场景中使用*args和**kwargs,帮助读者理解并掌握这些灵活的参数处理方式,需要的朋友可以参考下

今天,咱就来聊聊 Python 函数参数中的两个 “魔法参数”——*args 和 **kwargs,它们能让你的函数变得超级灵活,轻松应对各种复杂情况。不过对于新接触Python的同学来说是一个不好理解的概念,Up第一次接触也觉得过于灵活而不好理解。今天,Up尝试用通俗易懂的语言来说清楚

提前划重点

  • 什么是位置参数和关键字参数?
  • *args本质是个元组
  • **kwargs本质是个字典
  • 如何结合使用*args和**kwargs
  • 在装饰器中使用 * args 和 **kwargs

位置参数和关键字参数

在深入了解 * args 和 **kwargs 之前,咱们得先熟悉一下 Python 函数参数中的两个 “常规军”—— 位置参数和关键字参数,它们可是函数传参的基础。

位置参数,顾名思义,就是在调用函数时,按照参数的顺序依次传递给函数的参数,实参的位置和形参的位置要一一对应,就像排队领东西,先来的先领,顺序不能乱。比如说,咱们定义一个计算两数之和的函数:

def add_numbers(a, b):
    return a + b

这里的 a 和 b 就是位置参数,当我们调用这个函数时,就得按照顺序传入两个数:

result = add_numbers(3, 5)
print(result)  

在这个例子中, 3 会被赋值给 a, 5 会被赋值给 b,函数返回它们的和 8。

关键字参数呢,就灵活多了。它是指在调用函数时,通过指定参数名来为参数赋值,这样就不用拘泥于参数的位置顺序,让代码更加清晰易读。还是用刚才的加法函数举例,我们可以这样调用:

result = add_numbers(a=3, b=5)

甚至还可以交换顺序:

result = add_numbers(b=5, a=3)

不管顺序如何,只要参数名写对,就能准确地把值赋给对应的形参,是不是很方便?这在函数参数较多的时候特别有用,能让你一眼就看明白每个参数的含义。

另外,位置参数和关键字参数还能混合使用,不过要记住一条规则:位置参数必须在关键字参数之前。比如:

def greet(name, message):
    print(f"{message}, {name}!")

greet("小明", message="你好") 

这样写没问题,但要是写成 greet(message=“你好”, “小明”),Python 就会报错,因为违反了位置参数在前的原则。

*args 本质是个元组

*args 就像是一个 “参数收集器”,它能够把函数调用时多余的位置参数一股脑儿地收集起来,然后打包成一个元组(tuple)。这里要注意哦,名字不一定非得是args,写成numbers、values 之类的都没问题,关键是那个星号,它就像是一个 “魔法标记”,告诉 Python:“嘿,我要收集多余的位置参数啦!”

咱们来看个例子,假如你要写一个函数,计算任意多个数字的总和,你不确定用户会输入几个数字,这时候 * args 就能大显身手了:

def sum_numbers(*args):
    total = 0
    for number in args:
        total += number
    return total

在这个函数里,*args 就像一个口袋,不管你传入多少个位置参数,它都能接住,然后把这些参数变成一个元组。比如,咱们这样调用这个函数:

result = sum_numbers(1, 2, 3, 4, 5)
print(result)  

这里传入的 1、2、3、4、5 就会被 * args 收集起来,变成元组 (1, 2, 3, 4, 5),然后在函数内部,通过循环遍历这个元组,把每个数字相加,最终得到总和 15。

**kwargs 本质是个字典

讲完了*args,咱们再来看看另一位主角 ——**kwargs。它同样有个神奇的 “魔法标记”—— 两个星号**,有了它,函数就能把调用时传入的任意数量的关键字参数统统收集起来,整理成一个字典(dict)。和 * args 一样,名字不固定,写成 **params、**options 之类的都行,关键是那两个星号。

咱们来看个例子,假如你要写一个函数,用来展示一个人的详细信息,你不知道用户会提供哪些具体信息,这时候 **kwargs 就能派上用场啦:

def show_person_info(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

在这个函数里,**kwargs 就像一个万能的信息收纳盒,不管你传入多少个关键字参数,它都能接住,然后把这些参数变成一个字典。比如,咱们这样调用这个函数:

show_person_info(name="小明", age=20, city="北京")

这里传入的 name=“小明”、age=20、city=“北京” 就会被 **kwargs 收集起来,变成字典 {“name”: “小明”, “age”: 20, “city”: “北京”},然后在函数内部,通过遍历这个字典,把每个键值对都打印出来,展示出这个人的详细信息。

从函数定义的角度来看,**kwargs 也必须放在参数列表的最后面,这是为了让 Python 解释器能正确地识别参数。要是你把它放在前面,后面的参数就可能会被误认成关键字参数,导致程序出错。

如何结合使用 * args 和 **kwargs

了解了 * args 和 **kwargs 各自的特点,接下来咱们看看怎么把它们结合起来使用.

在实际编程中,有很多场景需要同时处理位置参数和关键字参数,而且数量还不确定。比如说,你要写一个函数来记录日志信息,日志可能包含一些固定的格式信息(类似关键字参数),还可能有一些额外的描述信息(类似位置参数),这时候 * args 和 **kwargs 就能完美配合。

咱们来看个例子:

def log_message(message_type, *args, **kwargs):
    print(f"[{message_type}]")
    for arg in args:
        print(arg)
    for key, value in kwargs.items():
        print(f"{key}: {value}")

在这个 log_message 函数中, message_type 是一个固定的位置参数,用来指定日志的类型,比如 “ERROR”、“INFO” 之类的。而 *args 用来接收一些额外的描述信息,**kwargs 则用来接收一些带有特定名称的详细信息,像日志发生的时间、代码行数等。

咱们这样调用这个函数:

log_message("INFO", "程序启动成功", time="2023-09-15 10:00:00", line_number=100)

这里,“程序启动成功” 会被args 收集,变成元组 (“程序启动成功”,),而 time=“2023-09-15 10:00:00” 和 line_number=100 会被**kwargs 收集,变成字典 {“time”: “2023-09-15 10:00:00”, “line_number”: 100}。函数内部先打印日志类型 “INFO”,接着遍历*args 打印额外描述,再遍历 **kwargs 打印详细信息,输出就会像这样:

[INFO]
程序启动成功
time: 2023-09-15 10:00:00
line_number: 100

在装饰器中使用 * args 和 **kwargs

聊完了 * args 和 **kwargs 的基本用法,咱再来看看它们在装饰器里如何使用!

对于装饰器不太熟悉的小伙伴,可以看一下Up上期的文章哦!

那*args 和 **kwargs 在装饰器里起什么作用呢?想象一下,如果被装饰的函数可能接收不定数量的参数,就像咱们之前讲的*args 和**kwargs 的用法,这时候装饰器里的内部函数就得用 *args 和**kwargs 来接收这些参数,然后原封不动地传给原函数,否则参数就传递不进去,会导致报错。

咱们来看个例子,假设你要写一个装饰器,用来记录函数的执行时间,不管这个函数接收几个参数,都能正常工作:

import time

def timeit(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"{func.__name__} 函数执行时间: {end_time - start_time} 秒")
        return result
    return wrapper

@timeit
def add_numbers(*args):
    return sum(args)

@timeit
def show_info(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

在这个例子中, timeit 是装饰器函数,它的内部函数 wrapper 使用 * args 和 **kwargs 接收任意数量的参数,然后把这些参数传给原函数 func,不管是 add_numbers 函数接收不定数量的位置参数,还是 show_info 函数接收不定数量的关键字参数,都能被 wrapper 函数正确接收并传递,同时还能记录下函数的执行时间。比如,咱们调用 add_numbers(1, 2, 3, 4, 5),会先记录开始时间,执行 add_numbers 函数计算总和,再记录结束时间,打印出函数执行时间,最后返回总和;调用 show_info(name=“小明”, age=20) 也是类似,先记录时间,打印信息,再返回 None(因为 show_info 函数没有返回值)。

要是装饰器里的内部函数不使用 * args 和 *kwargs,而是写死了固定的参数,那这个装饰器就只能用于特定参数数量和类型的函数,灵活性就大打折扣了。比如说,你把 wrapper 函数写成 def wrapper(a, b),那它就只能装饰接收两个位置参数的函数,要是用来装饰 add_numbers(args) 这种不定参数的函数,就会报错,提示参数数量不匹配。

所以说,args 和 **kwargs 在装饰器里就像是两座 “桥梁”,让装饰器能够无缝对接各种不同参数的函数,极大地拓展了装饰器的应用范围,让你的代码复用性更强,不管是简单的函数增强,还是复杂的框架开发,都离不开它们的身影,掌握了在装饰器中使用args 和 **kwargs 的技巧,你就能在 Python 编程的世界里更加游刃有余啦!

总结

到此这篇关于Python魔法参数args和kwargs的文章就介绍到这了,更多相关Python魔法参数args和kwargs内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python3.4实现远程控制电脑开关机

    Python3.4实现远程控制电脑开关机

    这篇文章主要为大家详细介绍了Python3.4实现远程控制电脑开关机的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-02-02
  • PHPMyAdmin及权限配置

    PHPMyAdmin及权限配置

    这篇文章主要介绍了PHPMyAdmin及权限配置,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2014-08-08
  • Python安装pygit2失败问题及解决

    Python安装pygit2失败问题及解决

    这篇文章主要介绍了Python安装pygit2失败问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • python文件读取失败怎么处理

    python文件读取失败怎么处理

    在本篇文章里小编给大家分享的是关于python文件读取失败怎么处理的相关文章,需要的朋友们参考下。
    2020-06-06
  • Python使用代理抓取网站图片(多线程)

    Python使用代理抓取网站图片(多线程)

    Python作为一门功能强大的脚本语言,经常被用来写爬虫程序,下面是使用Python通过代理进行多线程抓取图片,算是一个简易的python多线程爬虫
    2014-03-03
  • Python第三方常用模块openpyxl的简单介绍

    Python第三方常用模块openpyxl的简单介绍

    openpyxl模块是一个读写Excel 2010文档的Python库,如果要处理更早格式的Excel文档,需要用到额外的库,openpyxl是一个比较综合的工具,能够同时读取和修改Excel文档,下面这篇文章主要给大家介绍了关于Python第三方常用模块openpyxl的相关资料,需要的朋友可以参考下
    2022-08-08
  • Python优化算法之遗传算法案例代码

    Python优化算法之遗传算法案例代码

    优化算法,尤其是启发式的仿生智能算法在最近很火,它适用于解决管理学,运筹学,统计学里面的一些优化问题,这篇文章主要介绍了Python优化算法—遗传算法,需要的朋友可以参考下
    2023-02-02
  • Python CNN卷积神经网络实战教程深入讲解

    Python CNN卷积神经网络实战教程深入讲解

    CNN,即卷积神经网络,主要用于图像识别,分类。由输入层,卷积层,池化层,全连接层(Affline层),Softmax层叠加而成。卷积神经网络中还有一个非常重要的结构:过滤器,它作用于层与层之间(卷积层与池化层),决定了怎样对数据进行卷积和池化
    2022-12-12
  • python中的字典详细介绍

    python中的字典详细介绍

    这篇文章主要介绍了python中的字典详细介绍,字典是Python中最强大的数据类型之一,本文讲解了什么是字典、创建字典和给字典赋值 、字典的基本操作、映射类型操作符、映射相关的函数、字典的方法等内容,需要的朋友可以参考下
    2014-09-09
  • Python实现农历转换教程详解

    Python实现农历转换教程详解

    农历,是我国现行的传统历法。它是根据月相的变化周期,每一次月相朔望变化为一个月,参考太阳回归年为一年的长度,并加入二十四节气与设置闰月以使平均历年与回归年相适应。本文将用Python实现农历转换,需要的可以参考一下
    2022-03-03

最新评论