程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Usage of *args and * * kwargs in Python

編輯:Python

Just beginning to learn python When , About args,kwargs, and * I'm confused about the use of . I believe there are many people who are confused about this . I intend to dispel this doubt through this post ( I hope it can reduce doubts ).

Let's go through the following 5 Step by step to understand : 
1.  Use a function call to understand ’*’ The role of  
2.  Understand by the definition of a function ’*args’ The meaning of  
3.  Understand through the call of a function ’**’ The role of  
4.  Solve through the definition of a function ’**kwargs’ The meaning of  
5.  An application example is given to illustrate ’args’,’kwargs’ Application scenarios and why use it


Use a function call to understand ’*’ The role of

Define a function with three positional parameters ”fun”.

>>> def fun(a,b,c):
... print a,b,c
... 

Pass three position parameters to call this function

>>> fun(1,2,3)
1 2 3 # Output 

You can see that this function is called with three positional parameters , Three parameters will be printed

Now we define a sequence of three integers , And use ’*’

>>> l = [1,2,3]
>>> fun(*l)
1 2 3 # Output 

‘*’ What did you do ?

It breaks down the sequence ’l’ As a position parameter , And pass these position parameters to the function ’fun’ To call .

So split the sequence 、 The transmission position parameter means fun(*l) And fun(1,2,3) It's equivalent , because l = [1,2,3].

Try using other values in the sequence

>>> l = [4,8,0]
>>> fun(*l)
4 8 0 # Output 

Next, we try to put four numbers in the sequence , What happens when you call a function

>>> l = [3,6,9,1]
>>> fun(*l)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: fun() takes exactly 3 arguments (4 given)

We didn't get the right result in this call , Triggered TypeWrror abnormal . It's easy to see the error content ”fun() takes exactly 3 arguments (4 given)”.

Why does this happen ?

The sequence ’l’ Contains four values . therefore , We tried to call ’fun(*l)’,’l’ The middle value is split and passed to the function fun As a position parameter . however ,’l’ There are four values in , call ’fun(*l)’ Equivalent to calling ’fun(3,6,9,1)’, And because of the function ’fun’ Only three positional parameters are used in the definition , So we get this error . Empathy , The same procedure , The sequence ’l’ There are two numerical cases in , Be careful error Content .

>>> l = [7,4]
>>> fun(*l)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: fun() takes exactly 3 arguments (2 given)

‘*l’ Mixed with position parameters

>>> fun(23, *l)
23 7 4

ad locum , We give a position parameter 23, And subsequence ’l’ Two values removed 7 and 4, So the three parameters 23,7 and 4 It's passed to the function ’fun’

Understand by the definition of a function ’*args’ The meaning of

Modify the definition of the function :

>>> def fun(*args):
... print args
... 

Pass a position parameter to call this function

>>> fun(13)
(13,)

Pass multiple parameters to call this function

>>> fun(11,93,43)
(11, 93, 43)

‘*args’ What does it do in the function definition ?

It receives tuples as positional parameters , Instead of a common parameter list . ad locum ,”args” Is a tuple . Don't worry in our explanation ” Common parameters ” Understanding of this part , This will become clear in the following examples . In the last example , Call the function to print ”args” when , He will print all the values contained in the tuple .

Let's redefine the function ,”*args” And ” General parameter list ” A mixture of

>>> def fun(a, *args):
... print "a is ", a
... print "args is ", args
... 

In this function definition , Parameters ”a” representative ” General parameter list ”. 
Pass four position parameters to call this function :

>>> fun(11,12,34,43)
a is 11
args is (12, 34, 43)

It's easy to see ,’a’ Print out as 11, That is, the first position parameter .’a’ After that, there is only one parameter ’*args’. therefore ,’args’ Receive location parameters other than conventional parameters as tuples . So tuple args Receive as tuple 12,34 and 43.

We can also call this function by passing a positional parameter :

>>> fun(91)
a is 91
args is ()

ad locum , The only parameter we pass is assigned to the regular parameter ’a’. therefore ,’args’ Received an empty tuple .

Now that we have ”args”, We can extract the required values to do what we want to do . Redefinition ”fun”:

>>> def fun(a, *args):
... print a
... print "args can receive a tuple of any number of arguments, let's print all that."
... for arg in args:
... print arg
... 

Now we call this function by passing any parameter :

>>> fun(1,5,6,7)
1
args can receive a tuple of any number of arguments, let's print all that.
5
6
7

‘args’ Since it is a tuple , We can traverse it .

Now let's consider a scenario that uses all available parameters . We need to use two functions , The first function takes any number of arguments , And calculate the sum of other parameters except the first parameter through another function . Strange use cases , But we just need to review what we have done so far . Our goal is to get variable parameters in a function , And give these parameters to another function .

The first step is to write a function to calculate and . In this use case , This function will be applied in the first function .

>>> def calculate_sum(*args):
... return sum(args)
... 

In this function , We use built-in functions ’sum’, It uses tuples or sequences as arguments , Returns the sum of all elements of a tuple . From the definition of the function, we can see ’args’ Receive tuples containing positional parameters passed to this function . therefore ,’args’ It's a tuple , As a function ’sum’ Parameters of . Next, define another function , This function has any number of arguments , And use the previous function to calculate the sum of other parameters except the first parameter .

>>> def ignore_first_calculate_sum(a,*iargs):
... required_sum = calculate_sum(*iargs)
... print "sum is ", required_sum
... 

We can pass any parameter to this function . The first parameter is called the regular parameter ’a’ receive , Other parameters are ’iargs’ Receive as tuple . As we consider the case , Calculate the sum of parameters other than the first parameter . therefore , We use it ’a’ Receive the first parameter ,’iargs’ Is a tuple containing other parameters . We use the function ’calculate_sum’, but ’calculate_sum’ Multiple location parameters are required to be passed to as tuples ’args’. So in function ’ignore_first_calculate_sum’ The tuple needs to be disassembled ’iargs’, Then pass the element as a positional parameter to ’calculate_sum’. Be careful , use ’*’ Disassembly tuple .

therefore , We call it this way ’required_sum=calculate_sum(*iargs)’.

‘required_sum=calculate_sum(iargs)’ You can't call , Because it's passed on to ’calculate_sum’ Before that, we needed unpack The number . Don't use ’*’ Will not unpack The number , You can't perform the desired action . Call the function as follows :

>>> ignore_first_calculate_sum(12, 1,4,5)
sum is 10
>>> ignore_first_calculate_sum()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: ignore_first_calculate_sum() takes at least 1 argument (0 given)

Get the results you want .

Understand through the call of a function ’**’ The role of

Define a function with three parameters , And call... In many ways :

>>> def fun(a, b, c):
... print a, b, c
...
>>> fun(1,5,7)
1 5 7
>>> fun(a=1,b=5,c=7)
1 5 7

Use ”**” Call function , In this way, we need a dictionary . Be careful : Use... In function calls ”*”, We need tuples ; Use... In function calls ”**”, We need a dictionary

>>> d={'b':5, 'c':7}
>>> fun(1, **d)
1 5 7

In a function call ”**” What did you do ?

it unpack Dictionaries , The data items in the dictionary are passed to the function as key parameters . therefore ,”fun(1, **d)” The writing and ”fun(1, b=5, c=7)” equivalent . 
For a better understanding, give a few more examples :

>>> d = {'c':3}
>>> fun(1, 4, **d)
1 4 3
>>> d = {'a':7, 'b':3, 'c':8}
>>> fun(**d)
7 3 8

Let's make some mistakes :

>>> d = {'a':7, 'b':3, 'c':8, 'd':90}
>>> fun(**d)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: fun() got an unexpected keyword argument 'd'

This call is equivalent to ’fun(a=7, b=3, c=8, d=90)’, But the function only needs three arguments , So we get TypeError

>>> d = {'a':7, 'b':3,'d':90}
>>> fun(**d)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: fun() got an unexpected keyword argument 'd'

fun(**d) Equate to fun(a=7, b=3, d=90). Pass to function ”fun” The number of parameters you want , But there is no... In the parameter list ’d’, in call ’d’ A key value parameter passed to a function results in TypeError.

So, “*” unpacks the dictionary i.e the key values pairs in the dictionary as keyword arguments and these are sent as keyword arguments to the function being called. “” unpacks a list/tuple i.e the values in the list as positional arguments and these are sent as positional arguments to the function being called.

Understand through function definition ’**kwargs’ The meaning of

Redefining functions ”fun”:

>>> def fun(a, **kwargs):
... print a, kwargs
... 

This function uses only one positional parameter , Because there is only one variable in the general parameter list ’a’. But by ”**kwargs”, Multiple key value parameters can be passed .

>>> fun(1, b=4, c=5)
1 {'c': 5, 'b': 4}
>>> fun(45, b=6, c=7, d=8)
45 {'c': 7, 'b': 6, 'd': 8}

In the definition of a function ”**kwargs” What does it mean ? 
use ”**kwargs” Defined function ,kwargs Receive the key value parameter Dictionary of positions other than the general parameter list . ad locum ’kwargs’ It's a dictionary .

Redefine the function :

>>> def fun(a, **kwargs):
... print "a is ", a
... print "We expect kwargs 'b' and 'c' in this function"
... print "b is ", kwargs['b']
... print "c is ", kwargs['c']
...
>>> fun(1, b=3,c=5)
a is 1
We expect kwargs 'b' and 'c' in this function
b is 3
c is 5

Error call :

>>> fun(1, b=3, d=5)
a is 1
We expect kwargs 'b' and 'c' in this function
b is 3
c is
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in fun
KeyError: 'c'

The above call , Positional arguments ’a’ And key value parameters ’b’ It's all printed out . The other key value parameters passed in are ’d’, Function requires a key value argument ’c’, And from the dictionary ’kwargs’ obtain . But no key value was passed in ’c’, trigger KeyError. If a key value is passed in ’c’ Will not cause this error

>>> fun(1, b=3, d=5, c=9)
a is 1
We expect kwargs 'b' and 'c' in this function
b is 3
c is 9

because ’**kwargs’ In the function parameter list , We can pass any key value parameter . The above call passed in ”d”, But the function doesn't use .

Another mistake :

>>> fun(1, {'b':2, 'c':34})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: fun() takes exactly 1 argument (2 given)

Just like the error prompt , function ’fun’ Only one positional parameter is required , And gave two . Even though ’kwargs’ Receive key value parameters as a dictionary , But you can't pass a dictionary as a positional parameter to ’kwargs’. You can call as follows :

>>> fun(1, **{'b':2, 'c':34})
a is 1
We expect kwargs 'b' and 'c' in this function
b is 2
c is 34

Use in front of a dictionary ”**” Sure unpack Dictionaries , Pass the data items in the dictionary as key value parameters .

An application example is given to illustrate ’args’,’kwargs’ Application scenarios and why use it

Inheriting classes and overriding methods at any time , We should use ’*args’ and ’**kwargs’ Give the received positional parameters and key value parameters to the parent class method . Through examples, we can better understand

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

Define a class , We can create objects of classes , Class has a method ’save()’. Suppose that the objects of the class can pass through save() Method to the database . By function save() Parameter to determine whether to create a record in the database or update an existing record . 
Construct a new class , Like ’Model’ act , But we only save the object of this class after checking some conditions . This new class inherits ’Model’, rewrite ’Model’ Of ’save()’

>>> class ChildModel(Model):
... def save(self, *args, **kwargs):
... if self.name=='abcd':
... super(ChildModel, self).save(*args, **kwargs)
... else:
... return None
... 

In fact, the corresponding save action occurs in ’Model’ Of ’save’ In the method . So we call the subclass's ’save()’ Method, not ’Model’ Methods . Subclass ChildModel Of ’save()’ Receive any parent class save() Required parameters , And pass it to the parent class method . therefore , Subclass ’save()’ There are... In the method parameter list ”*args” and ”**kwargs”, They can receive any positional parameter or key value parameter , Except for the general parameter list .

Create below ChildModel Entity and save :

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

Here, you can transfer part-time parameters to the object save() Method . It's subclass save(),It received a dictionary containing the keyword argument in “kwargs”. Then it used “**” to unpack this dictionary as keyword arguments and then passed it to the superclass save(). So, superclass save() got a keyword argument ‘force_insert’ and acted accordingly.


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved