简体   繁体   English

**(双星/星号)和 *(星号/星号)对参数有何作用?

[英]What does ** (double star/asterisk) and * (star/asterisk) do for parameters?

What do *args and **kwargs mean? *args**kwargs是什么意思?

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

The *args and **kwargs is a common idiom to allow arbitrary number of arguments to functions as described in the section more on defining functions in the Python documentation. *args**kwargs是一个常见的习惯用法,允许函数使用任意数量的参数,如 Python 文档中有关定义函数的更多部分所述。

The *args will give you all function parameters as a tuple : *args将为您提供所有函数参数作为元组

def foo(*args):
    for a in args:
        print(a)        

foo(1)
# 1

foo(1,2,3)
# 1
# 2
# 3

The **kwargs will give you all keyword arguments except for those corresponding to a formal parameter as a dictionary. **kwargs将为您提供所有关键字参数,除了与作为字典的形式参数相对应的关键字参数。

def bar(**kwargs):
    for a in kwargs:
        print(a, kwargs[a])  

bar(name='one', age=27)
# name one
# age 27

Both idioms can be mixed with normal arguments to allow a set of fixed and some variable arguments:这两个习语都可以与普通参数混合,以允许一组固定和一些可变参数:

def foo(kind, *args, **kwargs):
   pass

It is also possible to use this the other way around:也可以反过来使用它:

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

obj = {'b':10, 'c':'lee'}

foo(100,**obj)
# 100 10 lee

Another usage of the *l idiom is to unpack argument lists when calling a function. *l习惯用法的另一种用法是在调用函数时解压缩参数列表

def foo(bar, lee):
    print(bar, lee)

l = [1,2]

foo(*l)
# 1 2

In Python 3 it is possible to use *l on the left side of an assignment ( Extended Iterable Unpacking ), though it gives a list instead of a tuple in this context:在 Python 3 中,可以在赋值的左侧使用*l ( Extended Iterable Unpacking ),尽管在这种情况下它给出了一个列表而不是一个元组:

first, *rest = [1,2,3,4]
first, *l, last = [1,2,3,4]

Also Python 3 adds new semantic (refer PEP 3102 ): Python 3 还添加了新语义(请参阅PEP 3102 ):

def func(arg1, arg2, arg3, *, kwarg1, kwarg2):
    pass

For example the following works in python 3 but not python 2:例如,以下适用于 python 3 但不适用于 python 2:

>>> x = [1, 2]
>>> [*x]
[1, 2]
>>> [*x, 3, 4]
[1, 2, 3, 4]

>>> x = {1:1, 2:2}
>>> x
{1: 1, 2: 2}
>>> {**x, 3:3, 4:4}
{1: 1, 2: 2, 3: 3, 4: 4}

Such function accepts only 3 positional arguments, and everything after * can only be passed as keyword arguments.这样的函数只接受 3 个位置参数,并且*之后的所有内容都只能作为关键字参数传递。

Note:笔记:

  • A Python dict , semantically used for keyword argument passing, are arbitrarily ordered. Python dict在语义上用于关键字参数传递,是任意排序的。 However, in Python 3.6, keyword arguments are guaranteed to remember insertion order.但是,在 Python 3.6 中,保证关键字参数会记住插入顺序。
  • "The order of elements in **kwargs now corresponds to the order in which keyword arguments were passed to the function." **kwargs中元素的顺序现在对应于关键字参数传递给函数的顺序。” - What's New In Python 3.6 - Python 3.6 的新功能
  • In fact, all dicts in CPython 3.6 will remember insertion order as an implementation detail, this becomes standard in Python 3.7.事实上,CPython 3.6 中的所有 dicts 都会记住插入顺序作为实现细节,这在 Python 3.7 中成为标准。

It's also worth noting that you can use * and ** when calling functions as well.还值得注意的是,您也可以在调用函数时使用*** This is a shortcut that allows you to pass multiple arguments to a function directly using either a list/tuple or a dictionary.这是一个快捷方式,允许您使用列表/元组或字典直接将多个参数传递给函数。 For example, if you have the following function:例如,如果您具有以下功能:

def foo(x,y,z):
    print("x=" + str(x))
    print("y=" + str(y))
    print("z=" + str(z))

You can do things like:您可以执行以下操作:

>>> mylist = [1,2,3]
>>> foo(*mylist)
x=1
y=2
z=3

>>> mydict = {'x':1,'y':2,'z':3}
>>> foo(**mydict)
x=1
y=2
z=3

>>> mytuple = (1, 2, 3)
>>> foo(*mytuple)
x=1
y=2
z=3

Note: The keys in mydict have to be named exactly like the parameters of function foo .注意: mydict中的键名必须与函数foo的参数完全相同。 Otherwise it will throw a TypeError :否则它会抛出一个TypeError

>>> mydict = {'x':1,'y':2,'z':3,'badnews':9}
>>> foo(**mydict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() got an unexpected keyword argument 'badnews'

The single * means that there can be any number of extra positional arguments.单个 * 表示可以有任意数量的额外位置参数。 foo() can be invoked like foo(1,2,3,4,5) . foo()可以像foo(1,2,3,4,5)一样被调用。 In the body of foo() param2 is a sequence containing 2-5.在 foo() 的主体中,param2 是一个包含 2-5 的序列。

The double ** means there can be any number of extra named parameters.双 ** 表示可以有任意数量的额外命名参数。 bar() can be invoked like bar(1, a=2, b=3) . bar()可以像bar(1, a=2, b=3)一样调用。 In the body of bar() param2 is a dictionary containing {'a':2, 'b':3 }在 bar() 的主体中 param2 是一个包含 {'a':2, 'b':3 } 的字典

With the following code:使用以下代码:

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

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

foo(1,2,3,4,5)
bar(1,a=2,b=3)

the output is输出是

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

What does ** (double star) and * (star) do for parameters? ** (双星)和* (星)对参数有什么作用?

They allow for functions to be defined to accept and for users to pass any number of arguments, positional ( * ) and keyword ( ** ).它们允许定义函数以接受并允许用户传递任意数量的参数、位置 ( * ) 和关键字 ( ** )。

Defining Functions定义函数

*args allows for any number of optional positional arguments (parameters), which will be assigned to a tuple named args . *args允许任意数量的可选位置参数(参数),它们将被分配给一个名为args的元组。

**kwargs allows for any number of optional keyword arguments (parameters), which will be in a dict named kwargs . **kwargs允许任意数量的可选关键字参数(参数),它们将位于名为kwargs的字典中。

You can (and should) choose any appropriate name, but if the intention is for the arguments to be of non-specific semantics, args and kwargs are standard names.您可以(并且应该)选择任何适当的名称,但如果意图是让参数具有非特定语义,则argskwargs是标准名称。

Expansion, Passing any number of arguments扩展,传递任意数量的参数

You can also use *args and **kwargs to pass in parameters from lists (or any iterable) and dicts (or any mapping), respectively.您还可以使用*args**kwargs分别从列表(或任何可迭代)和字典(或任何映射)传入参数。

The function recieving the parameters does not have to know that they are being expanded.接收参数的函数不必知道它们正在被扩展。

For example, Python 2's xrange does not explicitly expect *args , but since it takes 3 integers as arguments:例如,Python 2 的 xrange 没有明确地期望*args ,但因为它需要 3 个整数作为参数:

>>> x = xrange(3) # create our *args - an iterable of 3 integers
>>> xrange(*x)    # expand here
xrange(0, 2, 2)

As another example, we can use dict expansion in str.format :作为另一个例子,我们可以在str.format中使用 dict 扩展:

>>> foo = 'FOO'
>>> bar = 'BAR'
>>> 'this is foo, {foo} and bar, {bar}'.format(**locals())
'this is foo, FOO and bar, BAR'

New in Python 3: Defining functions with keyword only arguments Python 3 中的新功能:使用仅关键字参数定义函数

You can have keyword only arguments after the *args - for example, here, kwarg2 must be given as a keyword argument - not positionally:您可以在*args之后有仅关键字参数 - 例如,在这里, kwarg2必须作为关键字参数给出 - 而不是位置:

def foo(arg, kwarg=None, *args, kwarg2=None, **kwargs): 
    return arg, kwarg, args, kwarg2, kwargs

Usage:用法:

>>> foo(1,2,3,4,5,kwarg2='kwarg2', bar='bar', baz='baz')
(1, 2, (3, 4, 5), 'kwarg2', {'bar': 'bar', 'baz': 'baz'})

Also, * can be used by itself to indicate that keyword only arguments follow, without allowing for unlimited positional arguments.此外, *可以单独使用来表示后面只有关键字参数,而不允许无限的位置参数。

def foo(arg, kwarg=None, *, kwarg2=None, **kwargs): 
    return arg, kwarg, kwarg2, kwargs

Here, kwarg2 again must be an explicitly named, keyword argument:在这里, kwarg2再次必须是一个显式命名的关键字参数:

>>> foo(1,2,kwarg2='kwarg2', foo='foo', bar='bar')
(1, 2, 'kwarg2', {'foo': 'foo', 'bar': 'bar'})

And we can no longer accept unlimited positional arguments because we don't have *args* :而且我们不能再接受无限的位置参数,因为我们没有*args*

>>> foo(1,2,3,4,5, kwarg2='kwarg2', foo='foo', bar='bar')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() takes from 1 to 2 positional arguments 
    but 5 positional arguments (and 1 keyword-only argument) were given

Again, more simply, here we require kwarg to be given by name, not positionally:同样,更简单地说,这里我们要求kwarg按名称给出,而不是按位置给出:

def bar(*, kwarg=None): 
    return kwarg

In this example, we see that if we try to pass kwarg positionally, we get an error:在这个例子中,我们看到如果我们尝试按位置传递kwarg ,我们会得到一个错误:

>>> bar('kwarg')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bar() takes 0 positional arguments but 1 was given

We must explicitly pass the kwarg parameter as a keyword argument.我们必须明确地将kwarg参数作为关键字参数传递。

>>> bar(kwarg='kwarg')
'kwarg'

Python 2 compatible demos Python 2 兼容的演示

*args (typically said "star-args") and **kwargs (stars can be implied by saying "kwargs", but be explicit with "double-star kwargs") are common idioms of Python for using the * and ** notation. *args (通常说“star-args”)和**kwargs (可以通过说“kwargs”来暗示星号,但用“double-star kwargs”明确表示)是 Python 使用***表示法的常见习语. These specific variable names aren't required (eg you could use *foos and **bars ), but a departure from convention is likely to enrage your fellow Python coders.这些特定的变量名不是必需的(例如,您可以使用*foos**bars ),但是背离约定可能会激怒您的 Python 编码人员。

We typically use these when we don't know what our function is going to receive or how many arguments we may be passing, and sometimes even when naming every variable separately would get very messy and redundant (but this is a case where usually explicit is better than implicit).当我们不知道我们的函数将接收什么或我们可能传递多少参数时,我们通常会使用这些,有时即使单独命名每个变量也会变得非常混乱和冗余(但这种情况通常显式是比隐式更好)。

Example 1示例 1

The following function describes how they can be used, and demonstrates behavior.以下函数描述了如何使用它们,并演示了行为。 Note the named b argument will be consumed by the second positional argument before :请注意,命名的b参数将被之前的第二个位置参数消耗:

def foo(a, b=10, *args, **kwargs):
    '''
    this function takes required argument a, not required keyword argument b
    and any number of unknown positional arguments and keyword arguments after
    '''
    print('a is a required argument, and its value is {0}'.format(a))
    print('b not required, its default value is 10, actual value: {0}'.format(b))
    # we can inspect the unknown arguments we were passed:
    #  - args:
    print('args is of type {0} and length {1}'.format(type(args), len(args)))
    for arg in args:
        print('unknown arg: {0}'.format(arg))
    #  - kwargs:
    print('kwargs is of type {0} and length {1}'.format(type(kwargs),
                                                        len(kwargs)))
    for kw, arg in kwargs.items():
        print('unknown kwarg - kw: {0}, arg: {1}'.format(kw, arg))
    # But we don't have to know anything about them 
    # to pass them to other functions.
    print('Args or kwargs can be passed without knowing what they are.')
    # max can take two or more positional args: max(a, b, c...)
    print('e.g. max(a, b, *args) \n{0}'.format(
      max(a, b, *args))) 
    kweg = 'dict({0})'.format( # named args same as unknown kwargs
      ', '.join('{k}={v}'.format(k=k, v=v) 
                             for k, v in sorted(kwargs.items())))
    print('e.g. dict(**kwargs) (same as {kweg}) returns: \n{0}'.format(
      dict(**kwargs), kweg=kweg))

We can check the online help for the function's signature, with help(foo) , which tells us我们可以使用help(foo)查看函数签名的在线帮助,它告诉我们

foo(a, b=10, *args, **kwargs)

Let's call this function with foo(1, 2, 3, 4, e=5, f=6, g=7)让我们用foo(1, 2, 3, 4, e=5, f=6, g=7)调用这个函数

which prints:打印:

a is a required argument, and its value is 1
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 2
unknown arg: 3
unknown arg: 4
kwargs is of type <type 'dict'> and length 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: g, arg: 7
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args) 
4
e.g. dict(**kwargs) (same as dict(e=5, f=6, g=7)) returns: 
{'e': 5, 'g': 7, 'f': 6}

Example 2示例 2

We can also call it using another function, into which we just provide a :我们也可以使用另一个函数来调用它,我们只需在其中提供a

def bar(a):
    b, c, d, e, f = 2, 3, 4, 5, 6
    # dumping every local variable into foo as a keyword argument 
    # by expanding the locals dict:
    foo(**locals()) 

bar(100) prints: bar(100)打印:

a is a required argument, and its value is 100
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 0
kwargs is of type <type 'dict'> and length 4
unknown kwarg - kw: c, arg: 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: d, arg: 4
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args) 
100
e.g. dict(**kwargs) (same as dict(c=3, d=4, e=5, f=6)) returns: 
{'c': 3, 'e': 5, 'd': 4, 'f': 6}

Example 3: practical usage in decorators示例 3:装饰器中的实际用法

OK, so maybe we're not seeing the utility yet.好的,所以也许我们还没有看到该实用程序。 So imagine you have several functions with redundant code before and/or after the differentiating code.因此,假设您在微分代码之前和/或之后有几个带有冗余代码的函数。 The following named functions are just pseudo-code for illustrative purposes.以下命名函数只是用于说明目的的伪代码。

def foo(a, b, c, d=0, e=100):
    # imagine this is much more code than a simple function call
    preprocess() 
    differentiating_process_foo(a,b,c,d,e)
    # imagine this is much more code than a simple function call
    postprocess()

def bar(a, b, c=None, d=0, e=100, f=None):
    preprocess()
    differentiating_process_bar(a,b,c,d,e,f)
    postprocess()

def baz(a, b, c, d, e, f):
    ... and so on

We might be able to handle this differently, but we can certainly extract the redundancy with a decorator, and so our below example demonstrates how *args and **kwargs can be very useful:我们也许可以用不同的方式处理这个问题,但我们当然可以使用装饰器提取冗余,因此我们下面的示例演示了*args**kwargs如何非常有用:

def decorator(function):
    '''function to wrap other functions with a pre- and postprocess'''
    @functools.wraps(function) # applies module, name, and docstring to wrapper
    def wrapper(*args, **kwargs):
        # again, imagine this is complicated, but we only write it once!
        preprocess()
        function(*args, **kwargs)
        postprocess()
    return wrapper

And now every wrapped function can be written much more succinctly, as we've factored out the redundancy:现在每个包装函数都可以写得更简洁,因为我们已经排除了冗余:

@decorator
def foo(a, b, c, d=0, e=100):
    differentiating_process_foo(a,b,c,d,e)

@decorator
def bar(a, b, c=None, d=0, e=100, f=None):
    differentiating_process_bar(a,b,c,d,e,f)

@decorator
def baz(a, b, c=None, d=0, e=100, f=None, g=None):
    differentiating_process_baz(a,b,c,d,e,f, g)

@decorator
def quux(a, b, c=None, d=0, e=100, f=None, g=None, h=None):
    differentiating_process_quux(a,b,c,d,e,f,g,h)

And by factoring out our code, which *args and **kwargs allows us to do, we reduce lines of code, improve readability and maintainability, and have sole canonical locations for the logic in our program.通过分解出我们的代码, *args**kwargs允许我们这样做,我们减少了代码行数,提高了可读性和可维护性,并为我们的程序中的逻辑提供了唯一的规范位置。 If we need to change any part of this structure, we have one place in which to make each change.如果我们需要更改此结构的任何部分,我们有一个地方可以进行每次更改。

Let us first understand what are positional arguments and keyword arguments.让我们首先了解什么是位置参数和关键字参数。 Below is an example of function definition with Positional arguments.下面是一个带有位置参数的函数定义示例。

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

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

So this is a function definition with positional arguments.所以这是一个带有位置参数的函数定义。 You can call it with keyword/named arguments as well:您也可以使用关键字/命名参数调用它:

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

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

Now let us study an example of function definition with keyword arguments :现在让我们研究一个带有关键字参数的函数定义示例:

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

You can call this function with positional arguments as well:您也可以使用位置参数调用此函数:

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

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

So we now know function definitions with positional as well as keyword arguments.所以我们现在知道了带有位置参数和关键字参数的函数定义。

Now let us study the '*' operator and '**' operator.现在让我们研究一下'*'运算符和'**'运算符。

Please note these operators can be used in 2 areas:请注意,这些运算符可用于 2 个领域:

a) function call a)函数调用

b) function definition b)功能定义

The use of '*' operator and '**' operator in function call.函数调用中使用“*”运算符和“**”运算符。

Let us get straight to an example and then discuss it.让我们直接看一个例子,然后讨论它。

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.

So remember所以记住

when the '*' or '**' operator is used in a function call -当在函数调用中使用 '*' 或 '**' 运算符时 -

'*' operator unpacks data structure such as a list or tuple into arguments needed by function definition. '*' 运算符将数据结构(例如列表或元组)解压缩为函数定义所需的参数。

'**' operator unpacks a dictionary into arguments needed by function definition. '**' 运算符将字典解包为函数定义所需的参数。

Now let us study the '*' operator use in function definition .现在让我们研究一下函数定义中'*'运算符的使用。 Example:例子:

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

In function definition the '*' operator packs the received arguments into a tuple.在函数定义中,'*' 运算符将接收到的参数打包到一个元组中。

Now let us see an example of '**' used in function definition:现在让我们看一个在函数定义中使用'**'的例子:

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

In function definition The '**' operator packs the received arguments into a dictionary.在函数定义中,'**' 运算符将接收到的参数打包到字典中。

So remember:所以请记住:

In a function call the '*' unpacks data structure of tuple or list into positional or keyword arguments to be received by function definition.函数调用中,'*' 将元组或列表的数据结构解包为函数定义接收的位置或关键字参数。

In a function call the '**' unpacks data structure of dictionary into positional or keyword arguments to be received by function definition.函数调用中,'**' 将字典的数据结构解包为位置或关键字参数,以由函数定义接收。

In a function definition the '*' packs positional arguments into a tuple.函数定义中,'*' 将位置参数打包到一个元组中。

In a function definition the '**' packs keyword arguments into a dictionary.函数定义中,'**' 将关键字参数打包到字典中。

This table is handy for using * and ** in function construction and function call :该表对于在函数构造和函数调用中使用***很方便:

            In function construction         In function call
=======================================================================
          |  def f(*args):                 |  def f(a, b):
*args     |      for arg in args:          |      return a + b
          |          print(arg)            |  args = (1, 2)
          |  f(1, 2)                       |  f(*args)
----------|--------------------------------|---------------------------
          |  def f(a, b):                  |  def f(a, b):
**kwargs  |      return a + b              |      return a + b
          |  def g(**kwargs):              |  kwargs = dict(a=1, b=2)
          |      return f(**kwargs)        |  f(**kwargs)
          |  g(a=1, b=2)                   |
-----------------------------------------------------------------------

This really just serves to summarize Lorin Hochstein's answer but I find it helpful.这实际上只是总结了 Lorin Hochstein 的答案,但我发现它很有帮助。

Relatedly: uses for the star/splat operators have been expanded in Python 3相关:在 Python 3 中扩展了 star/splat 运算符的使用

* and ** have special usage in the function argument list. ***在函数参数列表中有特殊用途。 * implies that the argument is a list and ** implies that the argument is a dictionary. *意味着参数是一个列表, **意味着参数是一个字典。 This allows functions to take arbitrary number of arguments这允许函数采用任意数量的参数

For those of you who learn by examples!对于那些通过例子学习的人!

  1. The purpose of * is to give you the ability to define a function that can take an arbitrary number of arguments provided as a list (eg f(*myList) ). *的目的是让您能够定义一个函数,该函数可以接受以列表形式提供的任意数量的参数(例如f(*myList) )。
  2. The purpose of ** is to give you the ability to feed a function's arguments by providing a dictionary (eg f(**{'x' : 1, 'y' : 2}) ). **的目的是让您能够通过提供字典来提供函数的参数(例如f(**{'x' : 1, 'y' : 2}) )。

Let us show this by defining a function that takes two normal variables x , y , and can accept more arguments as myArgs , and can accept even more arguments as myKW .让我们通过定义一个函数来展示这一点,该函数接受两个普通变量xy ,并且可以接受更多参数作为myArgs ,并且可以接受更多参数作为myKW Later, we will show how to feed y using myArgDict .稍后,我们将展示如何使用myArgDict y

def f(x, y, *myArgs, **myKW):
    print("# x      = {}".format(x))
    print("# y      = {}".format(y))
    print("# myArgs = {}".format(myArgs))
    print("# myKW   = {}".format(myKW))
    print("# ----------------------------------------------------------------------")

# Define a list for demonstration purposes
myList    = ["Left", "Right", "Up", "Down"]
# Define a dictionary for demonstration purposes
myDict    = {"Wubba": "lubba", "Dub": "dub"}
# Define a dictionary to feed y
myArgDict = {'y': "Why?", 'y0': "Why not?", "q": "Here is a cue!"}

# The 1st elem of myList feeds y
f("myEx", *myList, **myDict)
# x      = myEx
# y      = Left
# myArgs = ('Right', 'Up', 'Down')
# myKW   = {'Wubba': 'lubba', 'Dub': 'dub'}
# ----------------------------------------------------------------------

# y is matched and fed first
# The rest of myArgDict becomes additional arguments feeding myKW
f("myEx", **myArgDict)
# x      = myEx
# y      = Why?
# myArgs = ()
# myKW   = {'y0': 'Why not?', 'q': 'Here is a cue!'}
# ----------------------------------------------------------------------

# The rest of myArgDict becomes additional arguments feeding myArgs
f("myEx", *myArgDict)
# x      = myEx
# y      = y
# myArgs = ('y0', 'q')
# myKW   = {}
# ----------------------------------------------------------------------

# Feed extra arguments manually and append even more from my list
f("myEx", 4, 42, 420, *myList, *myDict, **myDict)
# x      = myEx
# y      = 4
# myArgs = (42, 420, 'Left', 'Right', 'Up', 'Down', 'Wubba', 'Dub')
# myKW   = {'Wubba': 'lubba', 'Dub': 'dub'}
# ----------------------------------------------------------------------

# Without the stars, the entire provided list and dict become x, and y:
f(myList, myDict)
# x      = ['Left', 'Right', 'Up', 'Down']
# y      = {'Wubba': 'lubba', 'Dub': 'dub'}
# myArgs = ()
# myKW   = {}
# ----------------------------------------------------------------------

Caveats注意事项

  1. ** is exclusively reserved for dictionaries. **专供字典使用。
  2. Non-optional argument assignment happens first.非可选参数赋值首先发生。
  3. You cannot use a non-optional argument twice.您不能两次使用非可选参数。
  4. If applicable, ** must come after * , always.如果适用, **必须始终在*之后。

TL;DR TL;博士

Below are 6 different use cases for * and ** in python programming:以下是 python 编程中***的 6 个不同用例:

  1. To accept any number of positional arguments using *args : def foo(*args): pass , here foo accepts any number of positional arguments, ie, the following calls are valid foo(1) , foo(1, 'bar')使用*args接受任意数量的位置参数: def foo(*args): pass ,这里foo接受任意数量的位置参数,即以下调用是有效的foo(1) , foo(1, 'bar')
  2. To accept any number of keyword arguments using **kwargs : def foo(**kwargs): pass , here 'foo' accepts any number of keyword arguments, ie, the following calls are valid foo(name='Tom') , foo(name='Tom', age=33)使用**kwargs接受任意数量的关键字参数: def foo(**kwargs): pass ,这里 'foo' 接受任意数量的关键字参数,即以下调用是有效的foo(name='Tom') , foo(name='Tom', age=33)
  3. To accept any number of positional and keyword arguments using *args, **kwargs : def foo(*args, **kwargs): pass , here foo accepts any number of positional and keyword arguments, ie, the following calls are valid foo(1,name='Tom') , foo(1, 'bar', name='Tom', age=33)要使用*args, **kwargs接受任意数量的位置和关键字参数: def foo(*args, **kwargs): pass ,这里foo接受任意数量的位置和关键字参数,即以下调用是有效的foo(1,name='Tom') , foo(1, 'bar', name='Tom', age=33)
  4. To enforce keyword only arguments using * : def foo(pos1, pos2, *, kwarg1): pass , here * means that foo only accept keyword arguments after pos2, hence foo(1, 2, 3) raises TypeError but foo(1, 2, kwarg1=3) is ok.使用*强制仅使用关键字参数: def foo(pos1, pos2, *, kwarg1): pass ,这里*表示 foo 只接受 pos2 之后的关键字参数,因此foo(1, 2, 3)引发 TypeError 但foo(1, 2, kwarg1=3)就可以了。
  5. To express no further interest in more positional arguments using *_ (Note: this is a convention only): def foo(bar, baz, *_): pass means (by convention) foo only uses bar and baz arguments in its working and will ignore others.使用*_表示对更多位置参数不再感兴趣(注意:这只是一个约定): def foo(bar, baz, *_): pass bar baz按照约定) foo在其工作和会忽略别人。
  6. To express no further interest in more keyword arguments using \**_ (Note: this is a convention only): def foo(bar, baz, **_): pass means (by convention) foo only uses bar and baz arguments in its working and will ignore others.使用\**_表示对更多关键字参数不再感兴趣(注意:这只是一个约定): def foo(bar, baz, **_): pass表示(按照约定) foo仅使用barbaz参数它的工作,并会忽略其他人。

BONUS: From python 3.8 onward, one can use / in function definition to enforce positional only parameters.奖励:从 python 3.8 开始,可以在函数定义中使用/来强制执行仅位置参数。 In the following example, parameters a and b are positional-only , while c or d can be positional or keyword, and e or f are required to be keywords:在以下示例中,参数 a 和 b 是仅位置参数,而 c 或 d 可以是位置或关键字,而 e 或 f 必须是关键字:

def f(a, b, /, c, d, *, e, f):
    pass

From the Python documentation:来自 Python 文档:

If there are more positional arguments than there are formal parameter slots, a TypeError exception is raised, unless a formal parameter using the syntax "*identifier" is present;如果位置参数的数量多于形参槽的数量,则会引发 TypeError 异常,除非存在使用语法“*identifier”的形参; in this case, that formal parameter receives a tuple containing the excess positional arguments (or an empty tuple if there were no excess positional arguments).在这种情况下,该形式参数接收一个包含多余位置参数的元组(如果没有多余的位置参数,则接收一个空元组)。

If any keyword argument does not correspond to a formal parameter name, a TypeError exception is raised, unless a formal parameter using the syntax "**identifier" is present;如果任何关键字参数不对应于形式参数名称,则会引发 TypeError 异常,除非存在使用语法“**identifier”的形式参数; in this case, that formal parameter receives a dictionary containing the excess keyword arguments (using the keywords as keys and the argument values as corresponding values), or a (new) empty dictionary if there were no excess keyword arguments.在这种情况下,该形式参数接收一个包含多余关键字参数的字典(使用关键字作为键,参数值作为对应值),或者如果没有多余的关键字参数,则接收一个(新的)空字典。

* means receive variable arguments as tuple *表示以元组形式接收变量参数

** means receive variable arguments as dictionary **表示接收变量参数作为字典

Used like the following:使用如下:

1) single * 1) 单人 *

def foo(*args):
    for arg in args:
        print(arg)

foo("two", 3)

Output:输出:

two
3

2) Now ** 2) 现在**

def bar(**kwargs):
    for key in kwargs:
        print(key, kwargs[key])

bar(dic1="two", dic2=3)

Output:输出:

dic1 two
dic2 3

In Python 3.5, you can also use this syntax in list , dict , tuple , and set displays (also sometimes called literals).在 Python 3.5 中,您还可以在listdicttupleset显示(有时也称为文字)中使用此语法。 See PEP 488: Additional Unpacking Generalizations .请参阅PEP 488:附加拆包概括

>>> (0, *range(1, 4), 5, *range(6, 8))
(0, 1, 2, 3, 5, 6, 7)
>>> [0, *range(1, 4), 5, *range(6, 8)]
[0, 1, 2, 3, 5, 6, 7]
>>> {0, *range(1, 4), 5, *range(6, 8)}
{0, 1, 2, 3, 5, 6, 7}
>>> d = {'one': 1, 'two': 2, 'three': 3}
>>> e = {'six': 6, 'seven': 7}
>>> {'zero': 0, **d, 'five': 5, **e}
{'five': 5, 'seven': 7, 'two': 2, 'one': 1, 'three': 3, 'six': 6, 'zero': 0}

It also allows multiple iterables to be unpacked in a single function call.它还允许在单个函数调用中解压缩多个迭代。

>>> range(*[1, 10], *[2])
range(1, 10, 2)

(Thanks to mgilson for the PEP link.) (感谢 mgilson 提供 PEP 链接。)

I want to give an example which others haven't mentioned我想举一个别人没有提到的例子

* can also unpack a generator * 也可以解压生成器

An example from Python3 Document Python3 文档中的一个示例

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

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

unzip_x will be [1, 2, 3], unzip_y will be [4, 5, 6] unzip_x 将是 [1, 2, 3],unzip_y 将是 [4, 5, 6]

The zip() receives multiple iretable args, and return a generator. zip() 接收多个 iretable args,并返回一个生成器。

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

TL;DR TL;博士

It packs arguments passed to the function into list and dict respectively inside the function body.它将传递给函数的参数分别打包到函数体内的listdict中。 When you define a function signature like this:当您定义这样的函数签名时:

def func(*args, **kwds):
    # do stuff

it can be called with any number of arguments and keyword arguments.可以使用任意数量的参数和关键字参数调用它。 The non-keyword arguments get packed into a list called args inside the function body and the keyword arguments get packed into a dict called kwds inside the function body.非关键字参数被打包到函数体内名为args的列表中,关键字参数被打包到函数体内名为kwds的字典中。

func("this", "is a list of", "non-keyowrd", "arguments", keyword="ligma", options=[1,2,3])

now inside the function body, when the function is called, there are two local variables, args which is a list having value ["this", "is a list of", "non-keyword", "arguments"] and kwds which is a dict having value {"keyword" : "ligma", "options" : [1,2,3]}现在在函数体内,当函数被调用时,有两个局部变量, args是一个具有值的列表["this", "is a list of", "non-keyword", "arguments"]kwds是一个具有值{"keyword" : "ligma", "options" : [1,2,3]} dict


This also works in reverse, ie from the caller side.这也可以反向工作,即从调用方。 for example if you have a function defined as:例如,如果您将函数定义为:

def f(a, b, c, d=1, e=10):
    # do stuff

you can call it with by unpacking iterables or mappings you have in the calling scope:您可以通过解压缩调用范围内的可迭代对象或映射来调用它:

iterable = [1, 20, 500]
mapping = {"d" : 100, "e": 3}
f(*iterable, **mapping)
# That call is equivalent to
f(1, 20, 500, d=100, e=3)

Building on nickd's answer ...建立在nickd的答案...

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)

Output:输出:

1
(2, 3, 4, 5)

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

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

Basically, any number of positional arguments can use *args and any named arguments (or kwargs aka keyword arguments) can use **kwargs.基本上,任何数量的位置参数都可以使用 *args 并且任何命名参数(或 kwargs aka 关键字参数)都可以使用 **kwargs。

In addition to function calls, *args and **kwargs are useful in class hierarchies and also avoid having to write __init__ method in Python.除了函数调用之外,*args 和 **kwargs 在类层次结构中也很有用,并且还避免了在 Python 中编写__init__方法。 Similar usage can seen in frameworks like Django code.在 Django 代码等框架中可以看到类似的用法。

For example,例如,

def __init__(self, *args, **kwargs):
    for attribute_name, value in zip(self._expected_attributes, args):
        setattr(self, attribute_name, value)
        if kwargs.has_key(attribute_name):
            kwargs.pop(attribute_name)

    for attribute_name in kwargs.viewkeys():
        setattr(self, attribute_name, kwargs[attribute_name])

A subclass can then be然后可以是一个子类

class RetailItem(Item):
    _expected_attributes = Item._expected_attributes + ['name', 'price', 'category', 'country_of_origin']

class FoodItem(RetailItem):
    _expected_attributes = RetailItem._expected_attributes +  ['expiry_date']

The subclass then be instantiated as然后子类被实例化为

food_item = FoodItem(name = 'Jam', 
                     price = 12.0, 
                     category = 'Foods', 
                     country_of_origin = 'US', 
                     expiry_date = datetime.datetime.now())

Also, a subclass with a new attribute which makes sense only to that subclass instance can call the Base class __init__ to offload the attributes setting.此外,具有仅对该子类实例有意义的新属性的子类可以调用基类__init__来卸载属性设置。 This is done through *args and **kwargs.这是通过 *args 和 **kwargs 完成的。 kwargs mainly used so that code is readable using named arguments. kwargs 主要用于使代码可以使用命名参数读取。 For example,例如,

class ElectronicAccessories(RetailItem):
    _expected_attributes = RetailItem._expected_attributes +  ['specifications']
    # Depend on args and kwargs to populate the data as needed.
    def __init__(self, specifications = None, *args, **kwargs):
        self.specifications = specifications  # Rest of attributes will make sense to parent class.
        super(ElectronicAccessories, self).__init__(*args, **kwargs)

which can be instatiated as这可以被实例化为

usb_key = ElectronicAccessories(name = 'Sandisk', 
                                price = '$6.00', 
                                category = 'Electronics',
                                country_of_origin = 'CN',
                                specifications = '4GB USB 2.0/USB 3.0')

The complete code is here完整的代码在这里

*args and **kwargs : allow you to pass a variable number of arguments to a function. *args**kwargs :允许您将可变数量的参数传递给函数。

*args : is used to send a non-keyworded variable length argument list to the function: *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')

Will produce:将产生:

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 allows you to pass keyworded variable length of arguments to a function. **kwargs允许您将关键字可变长度的参数传递给函数。 You should use **kwargs if you want to handle named arguments in a function.如果你想在函数中处理命名参数,你应该使用**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")  

Will produce:将产生:

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

Given a function that has 3 items as argument给定一个有 3 个项目作为参数的函数

sum = lambda x, y, z: x + y + z
sum(1,2,3) # sum 3 items

sum([1,2,3]) # error, needs 3 items, not 1 list

x = [1,2,3][0]
y = [1,2,3][1]
z = [1,2,3][2]
sum(x,y,z) # ok

sum(*[1,2,3]) # ok, 1 list becomes 3 items

Imagine this toy with a bag of a triangle, a circle and a rectangle item.想象一下这个玩具有一袋三角形、一个圆形和一个矩形物品。 That bag does not directly fit.那个包不直接适合。 You need to unpack the bag to take those 3 items and now they fit.您需要打开袋子才能拿走这 3 件物品,现在它们都装好了。 The Python * operator does this unpack process. Python * 运算符执行此解包过程。

在此处输入图像描述

A good example of using both in a function is:在函数中同时使用两者的一个很好的例子是:

>>> 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')
{}

This example would help you remember *args , **kwargs and even super and inheritance in Python at once.这个例子将帮助你同时记住 Python 中的*args**kwargs甚至super和继承。

class base(object):
    def __init__(self, base_param):
        self.base_param = base_param


class child1(base): # inherited from base class
    def __init__(self, child_param, *args) # *args for non-keyword args
        self.child_param = child_param
        super(child1, self).__init__(*args) # call __init__ of the base class and initialize it with a NON-KEYWORD arg

class child2(base):
    def __init__(self, child_param, **kwargs):
        self.child_param = child_param
        super(child2, self).__init__(**kwargs) # call __init__ of the base class and initialize it with a KEYWORD arg

c1 = child1(1,0)
c2 = child2(1,base_param=0)
print c1.base_param # 0
print c1.child_param # 1
print c2.base_param # 0
print c2.child_param # 1

Context语境

  • python 3.x蟒蛇3.x
  • unpacking with ****开箱
  • use with string formatting与字符串格式一起使用

Use with string formatting与字符串格式一起使用

In addition to the answers in this thread, here is another detail that was not mentioned elsewhere.除了这个线程中的答案之外,这里还有其他地方没有提到的另一个细节。 This expands on the answer by Brad Solomon这扩展了布拉德所罗门的答案

Unpacking with ** is also useful when using python str.format .使用 python str.format时,使用**解包也很有用。

This is somewhat similar to what you can do with python f-strings f-string but with the added overhead of declaring a dict to hold the variables (f-string does not require a dict).这有点类似于您可以使用 python f-strings f-string执行的操作,但增加了声明 dict 来保存变量的开销(f-string 不需要 dict)。

Quick Example快速示例

  ## init vars
  ddvars = dict()
  ddcalc = dict()
  pass
  ddvars['fname']     = 'Huomer'
  ddvars['lname']     = 'Huimpson'
  ddvars['motto']     = 'I love donuts!'
  ddvars['age']       = 33
  pass
  ddcalc['ydiff']     = 5
  ddcalc['ycalc']     = ddvars['age'] + ddcalc['ydiff']
  pass
  vdemo = []

  ## ********************
  ## single unpack supported in py 2.7
  vdemo.append('''
  Hello {fname} {lname}!

  Today you are {age} years old!

  We love your motto "{motto}" and we agree with you!
  '''.format(**ddvars)) 
  pass

  ## ********************
  ## multiple unpack supported in py 3.x
  vdemo.append('''
  Hello {fname} {lname}!

  In {ydiff} years you will be {ycalc} years old!
  '''.format(**ddvars,**ddcalc)) 
  pass

  ## ********************
  print(vdemo[-1])

*args ( or *any ) means every parameters *args ( 或 *any ) 表示每个参数

def any_param(*param):
    pass

any_param(1)
any_param(1,1)
any_param(1,1,1)
any_param(1,...)

NOTICE : you can don't pass parameters to *args注意:您不能将参数传递给 *args

def any_param(*param):
    pass

any_param() # will work correct

The *args is in type tuple *args 在类型元组中

def any_param(*param):
    return type(param)

any_param(1) #tuple
any_param() # tuple

for access to elements don't use of *访问元素不要使用 *

def any(*param):
    param[0] # correct

def any(*param):
    *param[0] # incorrect

The **kwd **kwd

**kwd or **any This is a dict type **kwd 或 **any 这是一个 dict 类型

def func(**any):
    return type(any) # dict

def func(**any):
    return any

func(width="10",height="20") # {width="10",height="20")


  • def foo(param1, *param2): is a method can accept arbitrary number of values for *param2 , def foo(param1, *param2):是一种可以为*param2接受任意数量值的方法,
  • def bar(param1, **param2): is a method can accept arbitrary number of values with keys for *param2 def bar(param1, **param2):是一种可以接受任意数量的值的方法,带有*param2的键
  • param1 is a simple parameter. param1是一个简单的参数。

For example, the syntax for implementing varargs in Java as follows:例如,在 Java 中实现varargs的语法如下:

accessModifier methodName(datatype… arg) {
    // method body
}

"Infinite" Args with *args and **kwargs带有 *args 和 **kwargs 的“无限”参数

*args and **kwargs are just some way to input unlimited characters to functions, like: *args**kwargs只是向函数输入无限字符的某种方式,例如:


def print_all(*args, **kwargs):
    print(args) # print any number of arguments like: "print_all("foo", "bar")"
    print(kwargs.get("to_print")) # print the value of the keyworded argument "to_print"


# example:
print_all("Hello", "World", to_print="!")
# will print:
"""
('Hello', 'World')
!
"""
  • *args is the special parameter which can take 0 or more (positional) arguments as a tuple. *args是特殊参数,可以将 0 个或多个(位置)参数作为元组。

  • **kwargs is the special parameter which can take 0 or more (keyword) arguments as a dictionary. **kwargs是特殊参数,可以将 0 个或多个(关键字)参数作为字典。

*In Python, there are 2 kinds of arguments positional argument and keyword argument : *在 Python 中,有两种参数 位置参数和关键字参数

*args : *args

For example, *args can take 0 or more arguments as a tuple as shown below:例如, *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

Output:输出:

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

And, when printing *args , 4 numbers are printed without parentheses and commas:并且,在打印*args时,会打印 4 个数字,不带括号和逗号:

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

Output:输出:

1 2 3 4

And, args has tuple type:而且, args元组类型:

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

Output:输出:

<class 'tuple'>

But, *args has no type:但是, *args没有类型:

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

Output(Error):输出(错误):

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

And, normal parameters can be put before *args as shown below:并且,普通参数可以放在*args之前,如下所示:

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

Output:输出:

1 2 (3, 4)

But, **kwargs cannot be put before *args as shown below:但是, **kwargs不能放在*args之前,如下所示:

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

Output(Error):输出(错误):

SyntaxError: invalid syntax语法错误:语法无效

And, normal parameters cannot be put after *args as shown below:并且,普通参数不能放在*args之后,如下所示:

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

Output(Error):输出(错误):

TypeError: test() missing 2 required keyword-only arguments: 'num1' and 'num2' TypeError: test() 缺少 2 个必需的仅关键字参数:'num1' 和 'num2'

But, if normal parameters have default values, they can be put after *args as shown below:但是,如果普通参数有默认值,它们可以放在*args之后,如下所示:

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

Output:输出:

(1, 2) 3 4

And also, **kwargs can be put after *args as shown below:而且, **kwargs可以放在*args之后,如下所示:

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

Output:输出:

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

**kwargs : **kwargs

For example, **kwargs can take 0 or more arguments as a dictionary as shown below:例如, **kwargs可以接受 0 个或多个参数作为字典,如下所示:

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

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

Output:输出:

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

And, when printing *kwargs , 2 keys are printed:并且,在打印*kwargs时,会打印 2 个键:

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

Output:输出:

name age

And, kwargs has dict type:而且, kwargsdict类型:

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

Output:输出:

<class 'dict'>

But, *kwargs and **kwargs have no type:但是, *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)

Output(Error):输出(错误):

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

And, normal parameters can be put before **kwargs as shown below:并且,普通参数可以放在**kwargs之前,如下所示:

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

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

Output:输出:

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

And also, *args can be put before **kwargs as shown below:而且, *args可以放在**kwargs之前,如下所示:

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

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

Output:输出:

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

And, normal parameters and *args cannot be put after **kwargs as shown below:并且,普通参数和*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)

Output(Error):输出(错误):

SyntaxError: invalid syntax语法错误:语法无效

For both *args and **kwargs :对于*args**kwargs

Actually, you can use other names for *args and **kwargs as shown below.实际上,您可以为*args**kwargs使用其他名称,如下所示。 *args and **kwargs are used conventionally: *args**kwargs按照惯例使用:

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

Output:输出:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM