SoFunction
Updated on 2024-11-12

The role of *args and **kwargs in Python

write sth. upfront

It's not uncommon to read code that contains this*argscap (a poem)**kwargsThe expression:
For example, what should this output?

def foo(*args):
    print(args)
foo(1, 2, 3, 4, 5)

What about this one?

def foo(a, *args):
    print('a:', a)
    print('args:', args)
foo(1, 2, 3, 4, 5)

And this?

def bar(a,b,c):
    print(a,b,c)
bar(*[1,2,3])

Huh? How did the ∗ sign appear in front of a list? Is this correct?

*argscap (a poem)**kwargs, as well as separate *, ** what exactly does it do? What is the principle? Read this article and you'll understand completely!

*argsThere are two components as -*cap (a poem)args. The point here is that*
So to be clear.*argsWe're going topursue sth. back to its origins--Understanding*The role of the
Here's the blackboard, here's the kicker, and this is what many blogs write about that don't: the role of ∗, there are 2 - the packing parameter (pack) and the unpacking parameter (unpack)!

*argc

Packing parameters

Example 1:

def foo(*number):
    print(number)
foo(1, 2, 3, 4, 5)

(1, 2, 3, 4, 5)

What do we see? The function was given 5 arguments, it ran successfully, and the output was composed of the argumentstuple
We know that if number is not preceded by the ∗ sign, then it is clear that foo() can only take 1 argument, and it will report an error if more or less arguments are given. With ∗, it will run successfully.
So what's the principle?
The answer is that ∗ takes multiple arguments accepted by the function foo()1,2,3,4,5Packed into a tuple.(1,2,3,4,5)which is assigned to the formal parameter number.
We can verify that:
Example 2:

def foo(*number):
    for i in number:
        print(i)
    print(type(number))
foo(1, 2, 3, 4, 5)

1
2
3
4
5
<class 'tuple'>

As you can see from Example 2, number is indeed given to the(1,2,3,4,5)This real parameter.
Speak with reason, for more details seeOfficial python documentation, stick a picture over here:

Example 3:

def foo(a, *number):
    print('a:', a)
    print('number:', number)
    for i in number:
        print(i)
    print(type(number))
foo(1, 2, 3, 4, 5)
a: 1
number (2, 3, 4, 5)
2
3
4
5
<class 'tuple'>

As you can see from Example 3, the real parameter accepted by number becomes(2,3,4,5)The first parameter1formal parameteraAcceptance gone.
So here we can give the full version of the ∗-role:

The role of ∗: when a function accepts real parameters, it assigns them to the function's formal parameter in order, and if it encounters a formal parameter with ∗, then the real parameters that have not yet been assigned are packed (pack) in the form of a tuple, and assigned to that formal parameter with ∗.

It can be verified with a few more examples:
Example 4:

def foo(a, b, *number):
    print('a:', a)
    print('b:', b)
    print('number:', number)
    for i in number:
        print(i)
    print(type(number))
foo(1, 2, 3, 4, 5)
a: 1
b: 2
number: (3, 4, 5)
3
4
5
<class 'tuple'>

Example 5:

def foo(a, b, *number, c):
    print('a:', a)
    print('b:', b)
    print('c:', c)
    print('number:', number)
    for i in number:
        print(i)
    print(type(number))
foo(1, 2, 3, 4, 5)
Traceback (most recent call last):
  File "C:/Users/PycharmProjects/untitled10/", line 11, in <module>
    foo(1, 2, 3, 4, 5)
TypeError: foo() missing 1 required keyword-only argument: 'c'

Note that in Example 5 I specifically looked for an example that reported an error. Analyze for yourself why the error is reported. The answer is that the argument before c with ∗ accepts the rest of the real parameters, and c is not passed a real parameter!

Up to this point, the packing of ∗ (pack) It explains it all.
And a little tail:argsWhat is it?
The answer is:argsIt's just a convention to write a formal parameter, and it's fine if you write it as something else, but it's not good for standardizing the form. Like in our example, we use number all the time, and it works fine.

splitting parameter

Example 6:

def bar(a,b,c):
    print(a,b,c)
bar(*[1,2,3])

1 2 3

As you can see, ∗ is not used in a function definition this time, but in a function call. What does it do in this example?
The answer is: take the packed real parameters (tuples or lists), unpack them into individual ones, and assign them in turn to the formal parameters of the function.
In this example, the packed real parameter[1,2,3]is split, with 1 assigned to form parameter a, 2 to form parameter b, and 3 to form parameter c.

∗ The role of splitting is as simple as that. Understand the principle, and everything else is the same. Come up with two questions to practice:
Exercise: which of the following 3 programs works?
Example 7:

def bar(a,b):
    print(a,b)
bar(*[1, 2, 3])

Example 8:

def bar(a, b, c, d):
    print(a, b, c, d)
bar(*[1, 2, 3])

Example 9:

def bar(a, b, c, d=10):
    print(a, b, c, d)
bar(*[1, 2, 3])

The answer is that only Example 9 works. This is because, according to the principles we talked about, the real parameter 3 of Example 7 has no corresponding formal parameter to accept, and the formal parameter d of Example 8 has no real parameter to assign.

**kwargs

Packing parameters

the top*argsI've learned it.**kwargsAnd it's easy to understand.
**kwargsThere is also a two-part composition for -**cap (a poem)kwargs. The point here is ∗∗. That's right.kwargsJust a convention to write, no other special meaning, change the other also used, but for code readability, it is best to use the convention.
Again, ∗∗ has two roles - packing parameters (pack) and unpacking parameters (unpack)!
But the difference is still there, simply put:
Packing*argsis a combination of multipleposition parameterpacktuple**kwargsis a combination of multipleKeyword parameterspackdictionaries
Unpacking*argsis to split the packed parameters into individual ones and assign them to the function's formal parameters in turn.**kwargsis to split the dictionary's keys into individual ones and assign them sequentially to the function's formal parameters.
Example 10

def bar(**number):
    print(number)
bar(a=1, b=2, c=3)

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

splitting parameter

Example 11

def bar(a, b, c):
    print(a,b,c)
bar(**{'a': 1, 'b': 2, 'c': 3})

1 2 3

Note that there is a caveat here, that is, when using the ∗∗ way to disassemble the dictionary to assign a value to a formal parameter, you need the key name of the dictionary and the formal parameter of the function to be all the time, or else it will report an error, try it by yourself and you will know.

positional parameters, keyword parameters, the*args**kwargsMixing is done in a certain order, and I'm specifically not writing about it here. I'm not going to write about it here, because it shouldn't be a problem in itself, it's a basic skill that you should lay down when you learn functions. If you really need it, you can look it up yourself to deepen your impression, which is better than just reaching out to me.

to this article on Python *args and **kwargs understanding of the article is introduced to this, more related Python *args and **kwargs content, please search for my previous articles or continue to browse the following related articles I hope you will support me in the future more!