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

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

这篇文章主要介绍了Python中的*args和**kwargs,它们分别是可变位置参数和可变关键字参数,文章通过实际例子展示了如何在函数、装饰器等场景中使用*args和**kwargs,帮助读者理解并掌握这些灵活的参数处理方式,需要的朋友可以参考下

提前划重点

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

位置参数和关键字参数

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

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

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

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

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

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

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

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

甚至还可以交换顺序:

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

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

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

1
2
3
4
def greet(name, message):
print(f"{message}, {name}!")
greet("小明", message="你好")

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

*args 本质是个元组

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

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

1
2
3
4
5
def sum_numbers(*args):
total = 0
for number in args:
total += number
return total

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

1
2
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 就能派上用场啦:

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

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

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

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

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

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

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

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

咱们来看个例子:

1
2
3
4
5
6
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 则用来接收一些带有特定名称的详细信息,像日志发生的时间、代码行数等。

咱们这样调用这个函数:

1
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 打印详细信息,输出就会像这样:

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

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

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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的文章就介绍到这了。

 

 

学习资料见知识星球。

以上就是今天要分享的技巧,你学会了吗?若有什么问题,欢迎在下方留言。

快来试试吧,小琥 my21ke007。获取 1000个免费 Excel模板福利​​​​!

更多技巧, www.excelbook.cn

欢迎 加入 零售创新 知识星球,知识星球主要以数据分析、报告分享、数据工具讨论为主;

Excelbook.cn Excel技巧 SQL技巧 Python 学习!

你将获得:

1、价值上万元的专业的PPT报告模板。

2、专业案例分析和解读笔记。

3、实用的Excel、Word、PPT技巧。

4、VIP讨论群,共享资源。

5、优惠的会员商品。

6、一次付费只需129元,即可下载本站文章涉及的文件和软件。

文章版权声明 1、本网站名称:Excelbook
2、本站永久网址:http://www.excelbook.cn
3、本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长王小琥进行删除处理。
4、本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
5、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报。
6、本站资源大多存储在云盘,如发现链接失效,请联系我们我们会第一时间更新。

THE END
分享
二维码
< <上一篇
下一篇>>