The third function parameter
1. Position parameters
def power(x):
return x * x
For power(x)
functions, the parameter x
is a positional parameter.
power(x)
Change it to , power(x, n)
used to calculate x^n:
def power(x, n):
s = 1 while n > 0: n = n - 1 s = s * x return s
For this modified power(x, n)
function, any n-th power can be computed:
>>> power(5, 2)
25
>>> power(5, 3) 125
The modified power(x, n)
function has two parameters: x
and , both of which are positional parameters. When calling the function, the two incoming values are assigned to the parameters and n
in the order of their positions .x
n
2. Default parameters
There is no problem with the new power(x, n)
function definition, however, the old calling code fails because we have added a parameter and the old code cannot be called properly because of a missing parameter:
>>> power(5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: power() missing 1 required positional argument: 'n'
Python's error message is clear: The calling function is power()
missing a positional argumentn
def power(x, n=2): s = 1 while n > 0: n = n - 1 s = s * x return s
In this way, when we call power(5)
, it is equivalent to calling power(5, 2)
:
>>> power(5)
25
>>> power(5, 2) 25
For n > 2
other cases, n must be passed in explicitly, eg power(5, 3)
.
As you can see from the above example, default parameters can simplify function calls. There are a few things to keep in mind when setting default parameters:
One is that the mandatory parameters come first, and the default parameters come after, otherwise the Python interpreter will report an error (think about why the default parameters cannot be placed in front of the mandatory parameters);
The second is how to set the default parameters.
When the function has multiple parameters, put the parameters with large changes in the front, and put the parameters with small changes in the back. Parameters with small changes can be used as default parameters.
What are the benefits of using default parameters? The biggest advantage is that it can reduce the difficulty of calling functions.
Note: One thing to keep in mind when defining default parameters: default parameters must point to immutable objects!
To modify the above example, we can do it with None
this immutable object:
def add_end(L=None):
if L is None: L = [] L.append('END') return L
Now, no matter how many times it is called, there is no problem:
>>> add_end()
['END']
>>> add_end()
['END']
Why design str
, None
such immutable objects? Because once an immutable object is created, the data inside the object cannot be modified, which reduces errors caused by modifying data. In addition, since the object does not change, reading the object at the same time in a multitasking environment does not need to be locked, and there is no problem with reading at the same time. When we write a program, if we can design an immutable object, we should try to design it as an immutable object.
3. Variable parameters
function with variable number of arguments
def calc(*numbers):
sum = 0 for n in numbers: sum = sum + n * n return sum
Defining a variable parameter is compared to defining a list or tuple parameter by simply prefixing the parameter with a *
number. Inside the function, the parameter numbers
received is a tuple, so the function code is completely unchanged. However, when calling this function, you can pass in any number of parameters, including 0 parameters:
>>> calc(1, 2)
5
>>> calc() 0
What if you already have a list or tuple and you want to call it with a variadic argument? This can be done like this:
>>> nums = [1, 2, 3]
>>> calc(nums[0], nums[1], nums[2]) 14
This way of writing is of course feasible, but the problem is too cumbersome, so Python allows you to add a *
number in front of the list or tuple, and pass the elements of the list or tuple into variable parameters:
>>> nums = [1, 2, 3]
>>> calc(*nums) 14
*nums
Indicates that nums
all elements of this list are passed in as variable parameters. This notation is quite useful and common
4. Keyword Parameters
Variable parameters allow you to pass in zero or any number of parameters, which are automatically assembled into a tuple when the function is called. And keyword parameters allow you to pass in 0 or any number of parameters with parameter names, these keyword parameters are automatically assembled into a dict inside the function
def person(name, age, **kw): print('name:', name, 'age:', age, 'other:', kw)
What are keyword arguments for? It can extend the functionality of the function. For example, in theperson
function, we are guaranteed to receivename
andage
these two parameters, but if the caller is willing to provide more parameters, we can also receive. Imagine that you are doing a user registration function. Except for the user name and age, which are required, the others are optional. Using keyword parameters to define this function can meet the registration requirements.
>>> extra = {'city': 'Beijing', 'job': 'Engineer'} >>> person('Jack', 24, **extra) name: Jack age: 24 other: {'city': 'Beijing', 'job': 'Engineer'}
**extra
Indicates thatextra
all key-values of this dict are passed into the parameters of the function with keyword parameters**kw
, andkw
a dict will be obtained. Note thatkw
the obtained dict isextra
a copy, andkw
the correct changes will not affect the functions outside the function.extra
5. Named keyword arguments
For keyword arguments, the caller of the function can pass in any unrestricted keyword arguments. As for what is passed in, it needs to be kw
checked inside the function.
If you want to restrict the names of keyword arguments, you can use named keyword arguments, for example, only accept city
and job
as keyword arguments. The functions defined in this way are as follows:
def person(name, age, *, city, job): print(name, age, city, job)
Unlike keyword arguments **kw
, named keyword arguments require a special separator, *
and *
subsequent arguments are treated as named keyword arguments.
The calling method is as follows:
>>> person('Jack', 24, city='Beijing', job='Engineer') Jack 24 Beijing Engineer
If there is already a variadic parameter in the function definition, the following named keyword arguments no longer need a special separator *
:
def person(name, age, *args, city, job): print(name, age, args, city, job)
Named keyword arguments must be passed in the parameter name, unlike positional arguments. If no parameter name is passed in, the call will report an error:
>>> person('Jack', 24, 'Beijing', 'Engineer')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: person() takes 2 positional arguments but 4 were given
Due to the lack of parameter names city
and parameters in the call job
, the Python interpreter treats all 4 parameters as positional parameters, but the person()
function only accepts 2 positional parameters.
Named keyword arguments can have default values to simplify invocation:
def person(name, age, *, city='Beijing', job): print(name, age, city, job)
Since named keyword parameters city
have default values, you can call without city
parameters:
>>> person('Jack', 24, job='Engineer')
Jack 24 Beijing Engineer
When using named keyword arguments, pay special attention, if there are no variadic arguments, you must add one *
as a special separator. If missing *
, the Python interpreter will not recognize positional and named keyword arguments:
6. Parameter combination
With a tuple and dict, you can also call the above functions:
>>> args = (1, 2, 3, 4) >>> kw = {'d': 99, 'x': '#'} >>> f1(*args, **kw) a = 1 b = 2 c = 3 args = (4,) kw = {'d': 99, 'x': '#'} >>> args = (1, 2, 3) >>> kw = {'d': 88, 'x': '#'} >>> f2(*args, **kw) a = 1 b = 2 c = 3 d = 88 kw = {'x': '#'}
So, for any function, it can be func(*args, **kw)
called in a similar fashion, no matter how its parameters are defined.
summary
Python functions have a very flexible parameter form, which can implement simple calls or pass in very complex parameters.
The default parameter must be an immutable object. If it is a mutable object, there will be a logic error when the program runs!
Note the syntax for defining variadic and keyword arguments:
*args
is a variable parameter, and args receives a tuple;
**kw
is a keyword parameter, and kw receives a dict.
And the syntax for how to pass in variadic and keyword arguments when calling a function:
Variable parameters can be directly passed in: func(1, 2, 3)
, or you can assemble a list or tuple first, and then *args
pass in: func(*(1, 2, 3))
;
Keyword arguments can either be passed in directly: func(a=1, b=2)
, or you can assemble the dict first, and then **kw
pass in: func(**{'a': 1, 'b': 2})
.
Using *args
and **kw
is the idiom of Python, of course, other parameter names can also be used, but it is better to use the idiom.
Named keyword arguments are meant to limit the parameter names that the caller can pass in, and to provide default values.
Define named keyword arguments. Don't forget to write the delimiter when there are no variadic arguments *
, otherwise the definition will be a positional argument.