*args和**kwargs是什么意思?

def foo(x, y, *args):
def bar(x, y, **kwargs):

当前回答

让我们首先了解什么是位置参数和关键字参数。下面是带有位置参数的函数定义示例。

def test(a,b,c):
     print(a)
     print(b)
     print(c)

test(1,2,3)
#output:
1
2
3

这是一个带有位置参数的函数定义。也可以使用关键字/命名参数调用它:

def test(a,b,c):
     print(a)
     print(b)
     print(c)

test(a=1,b=2,c=3)
#output:
1
2
3

现在让我们研究一个带有关键字参数的函数定义示例:

def test(a=0,b=0,c=0):
     print(a)
     print(b)
     print(c)
     print('-------------------------')

test(a=1,b=2,c=3)
#output :
1
2
3
-------------------------

也可以使用位置参数调用此函数:

def test(a=0,b=0,c=0):
    print(a)
    print(b)
    print(c)
    print('-------------------------')

test(1,2,3)
# output :
1
2
3
---------------------------------

所以我们现在知道了带有位置参数和关键字参数的函数定义。

现在让我们研究一下“*”运算符和“**”运算符。

请注意,这些运算符可用于两个区域:

a) 函数调用

b) 函数定义

在函数调用中使用“*”运算符和“**”运算符。

让我们直接讲一个例子,然后讨论它。

def sum(a,b):  #receive args from function calls as sum(1,2) or sum(a=1,b=2)
    print(a+b)

my_tuple = (1,2)
my_list = [1,2]
my_dict = {'a':1,'b':2}

# Let us unpack data structure of list or tuple or dict into arguments with help of '*' operator
sum(*my_tuple)   # becomes same as sum(1,2) after unpacking my_tuple with '*'
sum(*my_list)    # becomes same as sum(1,2) after unpacking my_list with  '*'
sum(**my_dict)   # becomes same as sum(a=1,b=2) after unpacking by '**' 

# output is 3 in all three calls to sum function.

所以记住

在函数调用中使用“*”或“**”运算符时-

“*”运算符将列表或元组等数据结构解包为函数定义所需的参数。

“**”运算符将字典解包为函数定义所需的参数。

现在让我们研究函数定义中使用的“*”运算符。例子:

def sum(*args): #pack the received positional args into data structure of tuple. after applying '*' - def sum((1,2,3,4))
    sum = 0
    for a in args:
        sum+=a
    print(sum)

sum(1,2,3,4)  #positional args sent to function sum
#output:
10

在函数定义中,“*”运算符将收到的参数打包到一个元组中。

现在让我们看看函数定义中使用的“**”示例:

def sum(**args): #pack keyword args into datastructure of dict after applying '**' - def sum({a:1,b:2,c:3,d:4})
    sum=0
    for k,v in args.items():
        sum+=v
    print(sum)

sum(a=1,b=2,c=3,d=4) #positional args sent to function sum

在函数定义中,“**”运算符将收到的参数打包到字典中。

所以请记住:

在函数调用中,“*”将元组或列表的数据结构解包为要由函数定义接收的位置或关键字参数。

在函数调用中,“**”将字典的数据结构解包为函数定义要接收的位置或关键字参数。

在函数定义中,“*”将位置参数打包到元组中。

在函数定义中,“**”将关键字参数打包到字典中。

其他回答

在函数中同时使用两者的一个好例子是:

>>> def foo(*arg,**kwargs):
...     print arg
...     print kwargs
>>>
>>> a = (1, 2, 3)
>>> b = {'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(*a,**b)
(1, 2, 3)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,**b) 
((1, 2, 3),)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,b) 
((1, 2, 3), {'aa': 11, 'bb': 22})
{}
>>>
>>>
>>> foo(a,*b)
((1, 2, 3), 'aa', 'bb')
{}

我想举一个别人没有提到的例子

*也可以打开发电机

Python3文档中的示例

x = [1, 2, 3]
y = [4, 5, 6]

unzip_x, unzip_y = zip(*zip(x, y))

unzip x将为(1,2,3),unzip y将为(4,5,6)

zip()接收多个iretable参数,并返回一个生成器。

zip(*zip(x,y)) -> zip((1, 4), (2, 5), (3, 6))

*args是一个特殊的参数,可以将0个或多个(位置)参数作为元组。**kwargs是一个特殊的参数,可以将0个或多个(关键字)参数作为字典。

*在Python中,有两种参数位置参数和关键字参数:

*参数:

例如,*args可以采用0个或多个参数作为元组,如下所示:

           ↓
def test(*args):
    print(args)

test() # Here
test(1, 2, 3, 4) # Here
test((1, 2, 3, 4)) # Here
test(*(1, 2, 3, 4)) # Here

输出:

()
(1, 2, 3, 4)
((1, 2, 3, 4),)
(1, 2, 3, 4)

并且,当打印*参数时,将打印4个数字,不带括号和逗号:

def test(*args):
    print(*args) # Here
 
test(1, 2, 3, 4)

输出:

1 2 3 4

并且,args具有元组类型:

def test(*args):
    print(type(args)) # Here
 
test(1, 2, 3, 4)

输出:

<class 'tuple'>

但是,*参数没有类型:

def test(*args):
    print(type(*args)) # Here
 
test(1, 2, 3, 4)

输出(错误):

TypeError:type()需要1或3个参数

并且,正常参数可以放在*args之前,如下所示:

          ↓     ↓
def test(num1, num2, *args):
    print(num1, num2, args)
    
test(1, 2, 3, 4)

输出:

1 2 (3, 4)

但是,**kwargs不能放在*args之前,如下所示:

             ↓     
def test(**kwargs, *args):
    print(kwargs, args)
    
test(num1=1, num2=2, 3, 4)

输出(错误):

语法错误:无效语法

而且,正常参数不能放在*args之后,如下所示:

                 ↓     ↓
def test(*args, num1, num2):
    print(args, num1, num2)
    
test(1, 2, 3, 4)

输出(错误):

TypeError:test()缺少2个必需的仅关键字参数:“num1”和“num2”

但是,如果正常参数具有默认值,则可以将它们放在*args之后,如下所示:

                      ↓         ↓
def test(*args, num1=100, num2=None):
    print(args, num1, num2)
    
test(1, 2, num1=3, num2=4)

输出:

(1, 2) 3 4

此外,**kwargs可以放在*args之后,如下所示:

                    ↓
def test(*args, **kwargs):
    print(args, kwargs)
    
test(1, 2, num1=3, num2=4)

输出:

(1, 2) {'num1': 3, 'num2': 4}

**克瓦格斯:

例如,**kwargs可以使用0个或多个参数作为字典,如下所示:

             ↓
def test(**kwargs):
    print(kwargs)

test() # Here
test(name="John", age=27) # Here
test(**{"name": "John", "age": 27}) # Here

输出:

{}
{'name': 'John', 'age': 27}
{'name': 'John', 'age': 27}

并且,当打印*kwargs时,将打印两个键:

def test(**kwargs):
    print(*kwargs) # Here
 
test(name="John", age=27)

输出:

name age

并且,kwargs具有dict类型:

def test(**kwargs):
    print(type(kwargs)) # Here
 
test(name="John", age=27)

输出:

<class 'dict'>

但是,*kwargs和**kwargs没有类型:

def test(**kwargs):
    print(type(*kwargs)) # Here
 
test(name="John", age=27)
def test(**kwargs):
    print(type(**kwargs)) # Here
 
test(name="John", age=27)

输出(错误):

TypeError:type()需要1或3个参数

并且,正常参数可以放在**kwargs之前,如下所示:

          ↓     ↓
def test(num1, num2, **kwargs):
    print(num1, num2, kwargs)

test(1, 2, name="John", age=27)

输出:

1 2 {'name': 'John', 'age': 27}

此外,*args可以放在**kwargs之前,如下所示:

           ↓
def test(*args, **kwargs):
    print(args, kwargs)

test(1, 2, name="John", age=27)

输出:

(1, 2) {'name': 'John', 'age': 27}

并且,正常参数和*args不能放在**kwargs之后,如下所示:

                    ↓     ↓
def test(**kwargs, num1, num2):
    print(kwargs, num1, num2)

test(name="John", age=27, 1, 2)
                     ↓
def test(**kwargs, *args):
    print(kwargs, args)

test(name="John", age=27, 1, 2)

输出(错误):

语法错误:无效语法

对于*args和**kwargs:

实际上,您可以为*args和**kwargs使用其他名称,如下所示*args和**kwargs通常使用:

            ↓        ↓
def test(*banana, **orange):
    print(banana, orange)
    
test(1, 2, num1=3, num2=4)

输出:

(1, 2) {'num1': 3, 'num2': 4}

*args和**kwargs:允许您向函数传递可变数量的参数。

*args:用于向函数发送非关键字可变长度参数列表:

def args(normal_arg, *argv):
    print("normal argument:", normal_arg)

    for arg in argv:
        print("Argument in list of arguments from *argv:", arg)

args('animals', 'fish', 'duck', 'bird')

将产生:

normal argument: animals
Argument in list of arguments from *argv: fish
Argument in list of arguments from *argv: duck
Argument in list of arguments from *argv: bird

**夸尔斯*

**kwargs允许您向函数传递关键字可变长度的参数。如果要处理函数中的命名参数,应使用**kwargs。

def who(**kwargs):
    if kwargs is not None:
        for key, value in kwargs.items():
            print("Your %s is %s." % (key, value))

who(name="Nikola", last_name="Tesla", birthday="7.10.1856", birthplace="Croatia")  

将产生:

Your name is Nikola.
Your last_name is Tesla.
Your birthday is 7.10.1856.
Your birthplace is Croatia.

根据尼克的回答。。。

def foo(param1, *param2):
    print(param1)
    print(param2)


def bar(param1, **param2):
    print(param1)
    print(param2)


def three_params(param1, *param2, **param3):
    print(param1)
    print(param2)
    print(param3)


foo(1, 2, 3, 4, 5)
print("\n")
bar(1, a=2, b=3)
print("\n")
three_params(1, 2, 3, 4, s=5)

输出:

1
(2, 3, 4, 5)

1
{'a': 2, 'b': 3}

1
(2, 3, 4)
{'s': 5}

基本上,任何数量的位置参数都可以使用*args,任何命名参数(或kwargs又名关键字参数)都可以使用**kwargs。