Python fun(*args,**kwargs)中的*args,**kwargs参数含义及用法

  • Post author:
  • Post category:python




1. Python函数中的两种参数

我们知道,在Python中有两种参数

  • 位置参数(positional argument): 位置参数只能由参数位置决定
  • 关键词参数(keyword argument): 关键词参数只需要用 keyword = somekey 的方法即可传参

位置参数只能由参数位置决定。这也就决定了

位置参数一定要在前面

,否则关键词参数数量的变化都会使得位置无法判断。



2. 理解函数调用中的

*


*

的作用是将tuple或者list中的元素进行unpack,分开传入,作为多个参数。

def func(a,b,c)
	print(a,b,c)

alist = [1,2,3] # 这里alist的长度必须和函数中参数的个数相同,否则会报错
func(*alist) 	# 等同于 func(1, 2, 3)

1 2 3



2.1

*

做了什么

它拆开数列

alist

的数值作为

位置参数

,并把这些位置参数传给函数

func

来调用。

因此拆数列、传位置参数意味着

func(*alist)



func(1,2,3)

是等效的,因为

alist= [1,2,3]



3. 理解函数调用中的

**


**

的作用是unpack字典,并将字典中的数据项作为键值参数传给函数。

为了更好的理解举几个例子:

def func(a, b, c):
    print(a, b, c)
    
if __name__ == "__main__":
    dic = {'b': 2, 'c': 3}
    func(1, b=2, c=3)
    func(1, **dic)

1 2 3
1 2 3



4. 理解函数调用中的

*args



**kwargs


kwargs



keyword argument

的缩写,

args

就是

argument

。常见的是

*args



**kwargs

前面。

这两个的用途和效果如下:

def this_fun(a,b,*args,**kwargs):
	"""
	在这个函数定义中,参数”a, b”代表”常规参数列表”。
	args 接收元组作为位置参数,而非是常见的参数列表
	
	"""
    print(a,b)
    print(args)
    print(kwargs)

if __name__ = '__main__'
	this_fun(0,1,2,3,index1=11,index2=22)
	
0,1
(2, 3)
{'index2': 22, 'index1': 11}

也就是说,第一中不定的参数形式把剩下的没有关键字的参数收起来形成一个tuple,而第二种把有关键字的收起来做成一个字典。



5. 实例说明

args

,

kwargs

的应用场景



5.1 子类传参给父类方法

在任何时候继承类和重写方法的,我们应当用到

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")

定义一个类,我们可以创建类的对象,类的对象有一个方法

save()

.假设类的对象可以通过

save()

方法保存到数据库中。通过函数

save()

参数来决定是否在数据库中创建一条记录或者更新现存的记录。

构造一个新类,类有

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实体并调用save方法:

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

这里传参数给对象的save()方法。调用的是子类的save(), 它接收一个包含关键字参数

kwargs

的字典。然后,它使用

**

将字典作为关键字参数unpack,然后将其传递给超类

save()

。因此,超类

save()

获得关键字参数

force_insert

并执行相应的操作。



5.2 *args 实现sum

def my_sum(*args):
	res = 0
	for val in args:
		res += val
	return res
	
l1 = [4, 8]
l2 = [1,2,3]
print(my_sum(*l1)) 		# 12
print(my_sum(*l2)) 		# 6
print(my_sum(4,5,6)) 	# 15



参考


  1. https://blog.csdn.net/edogawachia/article/details/80588858

  2. https://blog.csdn.net/callinglove/article/details/45483097?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task



版权声明:本文为DlMmU原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。