Python function parameter type * ** difference

  • 2020-05-07 19:58:07
  • OfStack

When I first learned python, python was much simpler and easier to use than java. Memory recovery is similar to the accessibility analysis of hotspot, immutable objects are also of the Integer type as java, and with functions are similar to the new C++ feature, which is generally easier to understand. Just function part of the parameters of the "*" and "**", closure, and so on, really confusing 1, write down the concept after writing down, also hope that this article can help other beginners.

So this article is a study note, focusing on the use of the details and understanding, first introduced the function of various parameter types in the call and declaration of the difference, as well as the need to pay attention to the mix of 1 some details, followed by closure related content. Please correct me if there is anything wrong.

The function parameter does not take "*", "*" and "**" distinction
The key to
's understanding of this problem is to separate the three parts of the invocation from the declaration syntax.

function calls distinguish

1. Brief description of different types of parameters
The syntax of python function call is:


func(positional_args, keyword_args,
 *tuple_grp_nonkw_args, **dict_grp_kw_args)
 
 # For the sake of illustration , Then use the following function for an example
 def test(a,b,c,d,e):
  print a,b,c,d,e

For example, to illustrate the differences between the four types of invocation:

#-------------------------------
#positional_args way
>>> test(1,2,3,4,5)
1 2 3 4 5 # This method of calling function processing is equivalent to
a,b,c,d,e = 1,2,3,4,5
print a,b,c,d,e #-------------------------------
#keyword_args way
>>> test(a=1,b=3,c=4,d=2,e=1)
1 3 4 2 1 # This way of doing it is the same thing as doing it
a=1
b=3
c=4
d=2
e=1
print a,b,c,d,e #-------------------------------
#*tuple_grp_nonkw_args way
>>> x = 1,2,3,4,5
>>> test(*x)
1 2 3 4 5

So this is the same thing as this

a,b,c,d,e = x
print a,b,c,d,e
# Special instructions :x Will be able to dict type ,x for dick Type passes the key to the function
>>> y
{'a': 1, 'c': 6, 'b': 2, 'e': 1, 'd': 1}
>>> test(*y)
a c b e d #---------------------------------
#**dict_grp_kw_args way
>>> y
{'a': 1, 'c': 6, 'b': 2, 'e': 1, 'd': 1}
>>> test(**y)
1 2 6 1 1 # This is the same thing as
a = y['a']
b = y['b']
... #c,d,e Needless to
print a,b,c,d,e

2. Some details about mixing different types of parameters
then explains the mixing of different parameter types. To understand the syntax of the mixing of different parameters, you need to understand the following.

First of all, it is important to understand that the parameter types used in function calls must be in strict order, not in random order, otherwise an error will be reported. For example, (a=1,2,3,4,5) will cause an error. (*x,2,3) would also be considered illegal.

Because #keyword_args and **dict_grp_kw_args specify the parameter 11, there is no order, so you only need to consider the order of the order assignment (positional_args) and the order of the list assignment (*tuple_grp_nonkw_args) EN_nonkw_args has a logical sequence.

Finally, parameters are not allowed to be assigned more than once.

For example, the logical sequence between the order assignment (positional_args) and the list assignment (*tuple_grp_nonkw_args) :


# Only in order , The list assignment has a logical sequence on the result
# The right example 1
>>> x = {3,4,5}
>>> test(1,2,*x)
1 2 3 4 5
# The right example 2
>>> test(1,e=2,*x)
1 3 4 5 2 # Wrong example
>>> test(1,b=2,*x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: test() got multiple values for keyword argument 'b' # The right example 1, Processing is equivalent to
a,b = 1,2 # The order parameter
c,d,e = x # A list of parameters
print a,b,c,d,e # The right example 2, Processing is equivalent to
a = 1 # The order parameter
e = 2 # Keyword parameter
b,c,d = x # A list of parameters # Wrong example , Processing is equivalent to
a = 1 # The order parameter
b = 2 # Keyword parameter
b,c,d = x # A list of parameters
# Here because b Multiple assignments result in an exception , It can be seen that only the order parameter and the list parameter have logi sequence relation

The function declaration distinguishes the

Once you understand the difference between different types of arguments in a function call, it's much easier to understand the difference between different arguments in a function declaration.

1. The parameter types in the function declaration describe

There are only three types of function declarations, arg, *arg, **arg they do the exact opposite of a function call. When called *tuple_grp_nonkw_args converts a list to a sequence argument, whereas *arg in the declaration converts a sequence assignment (positional_args) to a list. When invoked, **dict_grp_kw_args converts the dictionary to a keyword parameter, and **arg in the declaration converts the keyword parameter (keyword_args) to a dictionary in turn.
Note: *arg and **arg can be null values.

The following examples illustrate the above rules:


#arg, *arg and **arg Role for
def test2(a,*b,**c):
 print a,b,c
#---------------------------
#*arg and **arg You can pass no arguments
>>> test2(1)
1 () {}
#arg You have to pass parameters
>>> test2()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: test2() takes at least 1 argument (0 given) #----------------------------
#*arg Will arrange positional_args Convert to list
>>> test2(1,2,[1,2],{'a':1,'b':2})
1 (2, [1, 2], {'a': 1, 'b': 2}) {}
# The processing is equivalent to
a = 1 #arg Processing parameters
b = 2,[1,2],{'a':1,'b':2} #*arg Processing parameters
c = dict() #**arg Processing parameters
print a,b,c #-----------------------------
#**arg will keyword_args Convert to dictionary
>>> test2(1,2,3,d={1:2,3:4}, c=12, b=1)
1 (2, 3) {'c': 12, 'b': 1, 'd': {1: 2, 3: 4}}
# The processing is equivalent to
a = 1 #arg Processing parameters
b= 2,3 #*arg Processing parameters
#**arg Processing parameters
c = dict()
c['d'] = {1:2, 3:4}
c['c'] = 12
c['b'] = 1
print a,b,c

2. Processing order problem

The function always handles arg type arguments first, then *arg and **arg types.


def test2(a,*b,**c):
 print a,b,c
>>> test2(1, b=[1,2,3], c={1:2, 3:4},a=1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: test2() got multiple values for keyword argument 'a'
# And the reason that you get an error here is , Always come first arg Type parameter
# The function call is equivalent to
# To deal with arg Type parameters :
a = 1
a = 1  # Multiple assignments , Lead to abnormal
# Handles other types of parameters
...
print a,b,c

closure
python function, the original can only access to the two variables: the global, and local context (function). In fact, the function itself is also an object, also has its own scope. Closure through the combination of function and reference set, make the function can be defined in its area executed outside. This collection could be obtained by func_closure this reference collection. This is similar to the way python handles global variables, except that the global variable stores the reference set in the field of s 131en__.

In addition, the reason that old versions of python's internal functions cannot be used in other scopes is not because the variables in each scope are strictly isolated from each other, but because the functions lose references to the original context when they are separated from the original scope. It is important to note that the context information stored by the closure is a shallow copy, so the mutable object passed to the inner function can still be modified by other variables that have references to the object.

For example:


>>> def foo(x,y):
...     def bar():
...             print x,y
...     return bar
...
# To view func_closure Reference information
>>> a = [1,2]
>>> b = foo(a,0)
>>> b.func_closure[0].cell_contents
[1, 2]
>>> b.func_closure[1].cell_contents
0
>>> b()
[1, 2] 0 # Mutable objects can still be modified
>>> a.append(3)
>>> b.func_closure[0].cell_contents
[1, 2, 3]
>>> b()
[1, 2, 3] 0


Related articles: