Python with * parameters and with ** parameters: variable parameters

1. Theoretical explanation:

*parameters and **parameters are the key knowledge in Python parameters, they are all called variable parameters (arbitrary parameters), we often see * args , **kwargs in the code

When defined as a function: collect unmatched parameters to form a tuple or dict object

1. The * parameter collects all unmatched position parameters to form a tuple object, and the local variable args points to this tuple object

2. The ** parameter collects all unmatched keyword parameters to form a dict object, and the local variable kwargs points to this dict object

def temp(*args,**kwargs):
    pass

When called as a function: unpack function

1. The * parameter is used to unpack each element of the tuple object and pass it into the function as a positional parameter one by one

2. The ** parameter is used to unpack each element of the dict object and pass it into the function as a keyword parameter one by one 

my_tuple = ("wang","yuan","wai")
 
temp(*my_tuple)
#---等同于---#
temp("wangyuan","yuan","wai")
my_dict = {"name":"wangyuanwai","age":32}
 
temp(**my_dict)
#----等同于----#
temp(name="wangyuanwai",age=32)

Two, * args  example

It's normal not to understand these basic concepts for the time being, and it takes a process to fully understand... The next few * args  examples will illustrate these concepts, and I hope it can help every student who learns Python! !

1) The function print_str with two positional parameters

def print_str(first, second):
    print(first)
    print(second)

What happens when you call the print_str() function with only one parameter?

In [31]: print_str("hello")

TypeError: print_str() missing 1 required positional argument: 'second'

TypeError: The interpreter tells the print_str() function at the console that it needs 2 arguments, and you only passed 1 argument to the print_str() function!

Thinking: How to modify the print_str() function to accept one parameter, two parameters, or even more parameters of variable number?

2) Modify the print_str() function to accept one parameter or a variable number of parameters

Modify the last parameter of the print_str() function to a variable parameter *second

def print_str(first, *second):
    print(first)
    print(second)

At this point, let's pass another parameter to call the print_str() function to see what happens this time?

In [34]: print_str("hello")
hello
()

This time no more error is reported, the first string parameter "hello" passed in is printed out, and *second without the passed in parameter prints the string representation of a tuple object, that is, a bracket "()". Note: () means a tuple object with 0 elements!

Thinking: Why does the second variable become a tuple object? We continue to learn!

3) One more experiment, passing in four arguments to the print_str() function... what happens?

In [35]: print_str("hello","美女","小猫","青蛙")

hello
('美女', '小猫', '青蛙')

The first parameter "hello" is normally printed on the first line...

The second parameter "beauty", the third parameter "kitten", and the fourth parameter "frog" are assembled into a new tuple object inside the function, and this new tuple object will be assigned to the variable second , at this time the local variable second points to a tuple object

Description: The parameters passed in when the function is called will be used in the function in order from left to right. The leftmost parameter will be used (matched) by the positional parameter first first, and all remaining unmatched parameters will be automatically used. Collected into a new tuple object, and the local variable second will point to this new tuple object

Note: * parameters only collect unmatched positional parameters

4) When calling the print_str() function, what happens when a * parameter is directly passed in?

def print_str(first, *second):
    print(first)
    print(second)

Console call:

In [38]: numbers_strings = ("1","2","3","4","5")
    ...: print_str(*numbers_strings)  # 注意这里的*numbers_strings


1
('2', '3', '4', '5')

Explanation: When *numbers_strings appears in a function call, it is called unpacking (a "*" character is followed by a tuple object), and numbers_strings itself is a tuple object, so it is also called unpacking of tuples. The elements are unpacked into positional parameters one by one and passed into the function, so there is equality between the following two statements!

print_str(*numbers_strings) 

Equivalent to

print_str("1","2","3","4","5")  

5) When a function that does not define variable parameters is called, what happens when the * parameter is passed in?

def print_str(first, second):
    print(first)
    print(second)

Console call:

In [40]: numbers_strings = ("1","2")
    ...: print_str(*numbers_strings)


1
2

print_str(*numbers_string)

Equivalent to

print_str("1","2")

During the tuple unpacking process, each element will be put into the position parameter in turn, which shows the following characteristics of the tuple unpacking function:

1. Can be used in variable parameters

2. It can also be used on functions that do not define variable parameters

The tuple unpacking function is a completely separate function

Explanation again: *parameters have different functions when they appear in different positions of the function

1. When the * parameter appears in the function definition, it means variable parameter

2. When the * parameter appears in the function call, it means the unpacking function

Note: When unpacking a tuple, the number of elements in the tuple must be consistent with the total number of positional parameters of the function

Three, **kwargs example

1) In the function definition, there are two ** before the parameter name

def printStr(**anything):
    print(anything)
 

Call the printStr function with two keyword arguments and see what happens?

In [42]: printStr(first = 5, second = 100)


{'first': 5, 'second': 100}

The print result is the string form of the dict object, why does anything become a dict?

Explanation: When the function is called, if the incoming keyword parameters have matching positional parameters, the positional parameters will be used (matched) in priority to these keyword parameters, and all remaining unused (unmatched) keyword parameters will be assembled in the function In a dict object, the dict object will be assigned to the variable name anything after assembly, at this time the local variable anything points to a dict object

Note: **parameters only collect unmatched keyword arguments

2) Use the dictionary unpacking function when calling the function (add ** before the dict object)

def printStr(first, **dict):
    print(str(first) + "\n")
    print(dict)

Console call:

In [44]: printDic = {"name": "tyson", "age":"99"}
    ...: printStr(100, **printDic)

100

{'name': 'tyson', 'age': '99'}

 
#等同于

In [45]: printDic = {"name": "tyson", "age":"99"}
    ...: printStr(100, name = "tyson", age = "99") 


100

{'name': 'tyson', 'age': '99'}

Explanation: When the function is called, add ** in front of a dict object to indicate the unpacking of the dictionary. It will convert each key-value pair element in the dict object into keyword parameters one by one and pass them to the function middle.

Four. Summary

In Python syntax, when *parameters and **parameters appear in the parameter list of the function definition at the same time, it means that the parameter list can accept any number of parameters, and they are collectively called variable parameters.

When the function is defined

1. *args means that any number (including 0) of positional parameters can be accepted. When the function is called, all unused (unmatched) positional parameters will be automatically assembled into a tuple object in the function, and this tuple object will be assigned to local variable args

2. **kwargs indicates that any number (including 0) of keyword parameters can be accepted. When the function is called, all unused (unmatched) keyword parameters will be assembled into a dict object within the function, and the dict object will be Assignment to local variable kwargs

Note: When the function is defined, both exist at the same time, and *args must be placed before **kwargs

when the function is called

1. *args means that each element in the unpacked tuple object is passed to the called function as a position parameter

2. **kwargs means that each element in the unpacked dictionary object is passed into the called function as a keyword parameter

Precautions
1. Variable parameters, multiple parameters with variable number can be passed, including 0 parameters

2. Variable parameters must be defined after common parameters (also known as positional parameters, mandatory parameters, selected parameters, etc.) and default value parameters, because variable parameters will collect all [unmatched] parameters, if If variable parameters are defined in front, ordinary parameters and default value parameters cannot match the incoming parameters, because they are all collected in variable parameters.

def printStr(普通参数,默认值参数name="王员外",*参数,**参数):
    pass

3. The *parameter must be defined before the **parameter

def printStr(普通参数,*参数,**参数):
    pass

4. When calling a function containing *args parameters, do not directly pass in a tuple object. If a tuple object is passed in, then the tuple object will only become an unmatched element in the tuple object assembled in the function. We can pass in the elements of the tuple object using the tuple unpacking syntax, unpacking syntax: *tuple.

temp = (1,2,3,4,5)
 
def my_first(*args):
    print(args)
 
 
my_first(temp)  #temp只算一个参数,除非你有这个需求
 
 
my_first(*temp) #OK

5. When calling a function that contains **kwargs parameters, do not pass in a dictionary object directly. A dictionary object is only counted as one parameter, and an error will be reported at this time, because a dict object does not conform to the grammatical specification of keyword parameters, and the dictionary object can be used Dictionary unpacking syntax, unpacking syntax: **dict

my_book = {"first":"小当家", "seoncd": "我是baby"}
 
 
def my_blood(**kwargs):
    print(kwargs)
 
 
my_blood(my_book)   #作为一个字典对象传入
 
 
my_blood(**my_book) #一个一个的关键字参数传入

6. The variable name of the * parameter, generally use the variable name args, just a suggestion, you can call it whatever you want, it is just a local variable name

7. The variable name of the ** parameter, generally use the variable name kwargs, just a suggestion, you can call it whatever you want, it is also a local variable name

A function with positional parameters, default value parameters, and variable parameters (for reference)

def my_first_blood(first_name,last_name,age=0,*args,**kwargs):
    print(first_name)
    print(last_name)
    print(age)
    for ele in args:
        print(ele)
    for key,value in kwargs.items():
        print(key)
        print(value) 

Call method:

n [47]: my_first_blood("王", "员外")

员外
0

In [48]: 
    ...: my_first_blood("王", "员外", 32)

员外
32

In [49]: my_first_blood("王", "员外", 32, "北京", "海淀", style="开心")

员外
32
北京
海淀
style
开心

A function that only passes in keyword arguments, causing an error

def temp(say, **kwargs):
    print(say)
    print(kwargs)
 
 
temp(fk=100, hello=1000)

Since the positional parameter say cannot match the incoming keyword parameters fk and hello, this call will result in an error. A keyword parameter must match the name of a positional parameter before it can be used by a positional parameter. Change it as follows:

In [52]: temp(10,fk=100, hello=1000)

10
{'fk': 100, 'hello': 1000}

The unpacking function is not only tuple, but also list, str, and range

first = (1,2,3)
 
second = [1,2,3]
 
third = "123"
 
fourth = range(4)
 
 
print(*first)
 
print(*second)
 
print(*third)
 
print(*fourth)

5. Reuse example system description

Refer to the following code to verify the above theory through examples.

1. Parameters with default values

Before understanding the parameters with an asterisk (*), let’s look at the parameters with default values. The function definition is as follows:

def defaultValueArgs(common, defaultStr = "default", defaultNum = 0):
    print("Common args:", common)
    print("Default String:", defaultStr)
    print("Default Number:", defaultNum)

 (1) Call when parameters with default values ​​(defaultStr, defaultNum) do not pass parameters:

In [26]: defaultValueArgs("Test")
Common args: Test
Default String: default
Default Number: 0

(2) Parameters with default values ​​(defaultStr, defaultNum) can be passed directly when calling (defaultStr in the example below), or written in the form of "argsName = value" (defaultNum in the example below):

In [27]: defaultValueArgs("Test", "Str", defaultNum=1)
Common args: Test
Default String: Str
Default Number: 1

In [28]: defaultValueArgs("Test", defaultNum=1)
Common args: Test
Default String: default
Default Number: 1

Note: When the function is defined, all parameters after the first parameter with a default value must have a default value , otherwise, an error will be reported at runtime.

def defaultValueArgs(common, defaultStr = "default", defaultNum):
    print("Common args:", common)
    print("Default String:", defaultStr)
    print("Default Number:", defaultNum)

Compile output:

SyntaxError: non-default argument follows default argument

2. Function parameters with an asterisk (*)

A function with one parameter is defined as follows:

def singalStar(common, *rest):
    print("Common args: ", common)
    print("Rest args: ", rest)

(1) Parameters with an asterisk (*) are not passed:

In [3]: singalStar("hello")
Common args:  hello
Rest args:  ()

Parameters with an asterisk (*) default to an empty tuple when no parameters are passed.

(2) When a parameter with an asterisk (*) is passed in multiple values ​​(the number is greater than or equal to the number of parameters in the function definition):

In [4]: singalStar("hello", "world", 000)
Common args:  hello
Rest args:  ('world', 0)

It is not difficult to see that in the second method, the asterisk parameter combines multiple received parameters into a tuple. 

(3) When we directly pass the value of tuple type to the asterisk parameter:

In [5]: singalStar("hello", ("world", 000))
Common args:  hello
Rest args:  (('world', 0),)

At this point, the passed tuple value is used as an element in the tuple of the asterisk parameter.

(4) If we want to use the tuple as the parameter value of the asterisk parameter, just add "*" before the tuple value.

In [6]: singalStar("hello", *("world", 000))
Common args:  hello
Rest args:  ('world', 0)
In [7]: singalStar("hello", *("world", 000), "123")
Common args:  hello

3. Function parameters with two asterisks (**)

Functions with two asterisks (**) are defined as follows:

(1) The double asterisk (**) parameter does not pass a value:

In [9]: doubleStar("hello")
Common args:  hello
Double args:  {}

Parameters with double asterisks (**) default to an empty dictionary when no value is passed.

(2) Double asterisk (**) parameters when multiple parameters are passed in (the number is greater than or equal to the number of parameters in the function definition):

In [10]: doubleStar("hello", "Test", 24)
TypeError: doubleStar() takes 1 positional argument but 3 were given

In [11]: doubleStar("hello", x = "Test", y = 24)
Common args:  hello
Double args:  {'x': 'Test', 'y': 24}

It can be seen that the double asterisk parameter combines multiple received parameters into a dictionary, but it is different from the single asterisk in that the "args = value" method of passing the default value must be adopted at this time, the field before "=" becomes the key of the dictionary, and the field after "=" becomes the value of the dictionary.

(3) If you want to use a dictionary as the parameter value of the asterisk parameter, what should you do? Similar to the single asterisk parameter, " ** " is added before the dictionary value, and no value can be added after it.

In [12]: doubleStar("hello", {"name": "Test", "age": 24})
TypeError: doubleStar() takes 1 positional argument but 2 were given

In [13]: doubleStar("hello", **{"name": "Test", "age": 24}, {"name": "Test2", "age": 24})
SyntaxError: positional argument follows keyword argument unpacking

In [14]: doubleStar("hello", **{"name": "Test", "age": 24}, **{"name": "Test2", "age": 24})
TypeError: __main__.doubleStar() got multiple values for keyword argument 'name'

In [16]: doubleStar("hello", **{"name": "Test", "age": 24}, **{"name1": "Test1", "age1": 24})
Common args:  hello
Double args:  {'name': 'Test', 'age': 24, 'name1': 'Test1', 'age1': 24}

In [15]: doubleStar("hello", **{"name": "Test", "age": 24})
Common args:  hello
Double args:  {'name': 'Test', 'age': 24}

4. In some cases, single asterisk function parameters and double asterisk function parameters are used together:

In [17]: def singalAndDoubleStar(common, *single, **double):
    ...:     print("Common args: ", common)
    ...:     print("Single args: ", single)
    ...:     print("Double args: ", double)


In [18]: singalAndDoubleStar("hello")
Common args:  hello
Single args:  ()
Double args:  {}
In [19]: singalAndDoubleStar("hello", "world", 000)
Common args:  hello
Single args:  ('world', 0)
Double args:  {}
In [20]: singalAndDoubleStar("hello", "world", 000, {"name": "Test", "age": 24})
Common args:  hello
Single args:  ('world', 0, {'name': 'Test', 'age': 24})
Double args:  {}
In [21]: singalAndDoubleStar("hello", "world", 000, **{"name": "Test", "age": 24})
Common args:  hello
Single args:  ('world', 0)
Double args:  {'name': 'Test', 'age': 24}
In [22]: singalAndDoubleStar("hello", ("world", 000), {"name": "Test", "age": 24})
Common args:  hello
Single args:  (('world', 0), {'name': 'Test', 'age': 24})
Double args:  {}
In [23]: singalAndDoubleStar("hello", *("world", 000), {"name": "Test", "age": 24}) 
Common args:  hello
Single args:  ('world', 0, {'name': 'Test', 'age': 24})
Double args:  {}
In [24]: singalAndDoubleStar("hello", *("world", 000), **{"name": "Test", "age": 24})
Common args:  hello
Single args:  ('world', 0)
Double args:  {'name': 'Test', 'age': 24}


reference article

1. Python parameters with * and parameters with **

2. **_ kwargs in python function parameters **_ in python function parameters

3. Python's variable parameters, *parameters, **parameters, and incoming *parameters, **parameter unpacking, *args, **kwargs understanding_Call me Wang Yuanwai's blog-CSDN blog_python parameters* *​​​​​​

4、https://www.jb51.net/article/206158.htm

5. The understanding of Python's variable parameters, *parameters, **parameters, and incoming *parameters, **parameter unpacking, *args, **kwargs_Call me Wang Yuanwai blog-CSDN blog_python parameters* * 

Guess you like

Origin blog.csdn.net/qimo601/article/details/126480833