<返回更多

Python中*args和*kwargs

2020-09-11    
加入收藏
Python中*args和*kwargs

 

Python的代码中经常会见到这两个词 args 和 kwargs,前面通常还会加上一个或者两个星号。

注:这其实就是 Python 中可变参数的两种形式,并且 *args 必须放在 **kwargs 的前面,因为位置参数在关键字参数的前面。

我们将通过以下5方面来理解:

  1. *的作用
  2. *args的用法
  3. **的作用
  4. **kwargs的用法
  5. 实例

*的作用

通过一个函数调用来理解“*”的作用

#定义一个含三位置参数的函数
>>>def fun(a, b, c):
...	print a,b,c#传三个位置参数,调用此函数>>> fun(1,2,3)
1 2 3	# 输出

现在我们定义一个含三个整数的数列,并使用‘*’

>>> var = [1, 2, 3]
>>> fun(*var)
1 2 3	# 输出

'*'做了什么?它拆开数列'var'的数值作为位置参数,并把这些位置参数传给函数‘fun’来调用。

这意味着fun(*var)与fun(1,2,3)是等效的,因为var=[1,2,3]

注:*var与位置参数可混合使用

*args的用法

"*args"在函数定义中是做什么用的?它接收元组作为位置参数,而非是常见的参数列表。在这里,“args”是个元组。

“args”与“常规参数列表”混合使用

#在函数定义中,参数‘a’代表‘常规参数列表’
>>> def fun(a, *args):
...	print("a is ", a)
...	print("args is ", args)
#‘args’接收除常规参数之外的位置参数作为元组>>> fun(11, 12, 13, 14)
a is 11
args is (12, 13, 14)

注:'args'既然是元组,我们就可以遍历它。

**的作用

通过一个函数调用来理解“**”的作用

# 定义一个三参数的函数
>>> def fun(a, b, c):
...	print(a, b, c)...>>> func(1, 2, 3)
1 2 3
>>> fun(a=1, b=2, c=3)
1 2 3

使用“**”调用函数,这种方式我们需要一个字典。

>>> var = {'b' : 2, 'c' : 3}
>>> fun(1, **var)
1 2 3

注:在函数调用中使用‘*’,我们需要元组;在函数调用中使用‘**’,我们需要一个字典

“**”做了什么?它unpack字典,并将字典中的数据项作为键值参数传给函数。因此,fun(1, **var)的写法与fun(1, b=2, c=3)等效。

**kwargs的用法

在函数定义中“**kwargs”意味着什么?kwargs接收除常规参数列表外的键值参数字典,在这里'kwargs'是个字典。

重新定义函数:

>>> def fun(a, **kwargs):
...	print("a is ", a)
...	print("We expect kwargs 'b' and 'c' in this function")
...	print("b is ", kwargs['b'])
...	print("c is ", kwargs['c'])
...>>> fun(1, b=3, c=5)
a is 1
We expect kwargs 'b' and 'c' in this function
b is 3
c is 5

注:在一个字典前使用“**”可以unpack字典,传字典中的数据项作为键值参数。

实例

通过一个应用实例来说明'args','kwargs'应用场景以及为何要使用它。

在继承类和重写方法的时候,我们可以用到’*args’和’**kwargs’将接收到的位置参数和键值参数给父类方法,通过实例我们更好的理解。

>>> class Model(object):
...	def __init__(self, name):
...		self.name = name...	def save(self, force_update=False, force_insert=False):
...		if force_update and force_insert:
...			raise ValueError("Cannot perform both operations")
...		if force_update:
...			print("Updated an existing record")
...		if force_insert:
...			print("Created a new record")

构造一个新类,类有’Model’的行为,但我们只有检查一些条件后才会保存这个类的对象。这个新类继承’Model’,重写’Model’的’save()’

>>> class ChildModel(Model):
...	def save(self, *args, **kwargs):
    ...             if self.name=='abcd':
...                     super(ChildModel, self).save(*args, **kwargs)...             else:
...                     return None

实际上对应的保存动作发生在’Model’的’save’方法中。所以我们调用子类的的’save()’方法而非’Model’的方法.子类ChildModel的’save()’接收任何父类save()需要的参数,并传给父类方法。因此,子类’save()’方法参数列表中有”*args”和”**kwargs”,它们可以接收任意位置参数或键值参数,常规参数列表除外。

下面创建ChildModel实体并保存:

>>> c=ChildModel('abcd')
>>> c.save(force_insert=True)
Created a new record
>>> c.save(force_update=True)
Updated an existing record

这里传键值参数给对象的save()方法,调用的是子类的save()。

声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍最近更新
更多资讯 >>>