Python随笔-2

本文最后更新于:2022年5月23日 凌晨

前言

在学习装饰器的时候,其中有提到过*args和**kwargs可以让装饰器变得更加强大、有用。
文章也简单地说明了下他们的作用,不过想了想这部分貌似也能水一篇文章还是挺重要的,遂写了一篇随笔记一下。
当然相关的函数参数解包的内容也一起写在随笔里了。

正文

它们有什么用

它们能让函数接受可选参数。当然,这里的可选参数可能并不像你想的那样,我是说,不是这样的可选参数:

1
2
def add(a=0, b=0)
return a + b

而是这样的:

1
2
3
def test(*args, **kwargs):
print(args)
print(kwargs)

上述函数可以传递任意多的参数,也能不传递参数。在这里arg会收集位置参数组成元组,kwargs会收集额外的关键字参数组成字典。如果不传递参数,那么args和kwargs都为空。

1
2
3
4
5
6
7
>>> test(1,2,3,4,k=1,j=2,l=3)
(1, 2, 3, 4)
{'k': 1, 'j': 2, 'l': 3}

>>> test()
()
{}

实际起作用的是语法分别是星号(*)和双星号(**),args和kwargs只是命名约定。

函数参数解包

解包操作符*和**可以用来从序列和字典中“解包”函数参数。
比如我们现在有这么一个函数,接受三个参数并返回他们的和。

1
2
def add(a, b, c):
return a + b + c

如果我们需要传递的参数在一个列表中,我们得这么做才能传递过去:add(a_list[0], a_list[1], a_list[2])
但是这看上去非常笨不是吗?所幸我们有解包操作符*,现在,它可以这么写了:add(*a_list)在函数调用时,在可迭代对象前面放一个*能解包这个参数,将其中的元素作为单独的位置参数传递给被调用的函数。
另一个解包操作符**则是用于从字典中解包关键字参数,比如有这么一个字典:a_dict = {'a' = 1, 'b' = 2, 'c' = 3},那么要将它传入add()中,就可以这么写:add(**a_dict),则其中的值会按插入顺序传递给对应位置的参数。
需要说明的是,解包的时候会匹配字典键和函数参数,在上边,add中的a参数会接受字典中与’a’键相关的值。
而如果使用*对字典进行解包的话,则是将所有的按插入顺序传递给函数。

传递可选参数

了解了函数参数解包后,我们就可以用它来从一个函数中将可选参数传递给另外一个函数了,并且,参数在传递之前还可以进行修改。
比如:

1
2
3
4
def test1(*args, **kwargs):
new_args = args + (5, )
kwargs['k'] = 5
test(*new_args, **kwargs)

这种技术适用于创建子类和编写包装函数(如装饰器)。[1]
例如在扩展父类的行为时,子类中的构造函数不用再带有完整的参数列表,因而适用于处理那些不受我们控制的API。
一般情况下,自己定义的类层次中并不会用到这种技术。这通常用于修改或覆盖某些外部类中的行为,而自己又无法控制这些外部类。


  1. 《Python Tricks 深入理解python特性》 [德]达恩·巴德尔 人民邮电出版社

这里有一只爱丽丝

希望本文章能够帮到您~


Python随笔-2
https://map1e-g.github.io/2022/05/13/python-essay-2/
作者
MaP1e-G
发布于
2022年5月13日
许可协议