Advanced usage of Python function parameters
- 2021-12-09 09:08:53
- OfStack
(2) Accept any number of keyword parameters (3) Accept any number of position parameters and keyword parameters 3, keyword-only parameters 3, optional parameters (parameters with default values)
1. Keyword parameters and position parameters
Keyword parameters (
positional argument
) and position parameters (
keyword argument
)
Python
The parameters of a function are divided into keyword parameters and positional parameters according to the form of parameters passed by the function when it is called (note that it is not when the function is defined).
(1) Keyword parameters
Keyword parameters are defined by identifiers such as
name=
), or pass it in a dictionary booted by * * as follows:
complex(real=3, imag=5)
complex(**{'real': 3, 'imag': 5})
(2) Position parameters
A parameter that is either a keyword parameter or a position parameter. In addition to passing alone it can be passed in an iterative sequence (lists tuples and so on) booted by *. As shown below:
complex(3, 5)
complex(*(3, 5))
The positional parameter is always placed at the top of the argument list of the function, and the keyword parameter must be placed after the positional parameter. The positional relationship between them is as follows:
def func(arg1, arg2, kwarg1, kwarg2):
func(1, 2, kwarg1=3, kwarg2=4)
Here
arg1
,
arg2
Is a position parameter,
kwarg1
,
kwarg2
Is a keyword parameter. Keyword parameter
key
(That is, here
'kwarg1=3'
In
keyword argument
0
,
'kwarg2=4'
In '
kwarg2'
) Be sure to match the parameter name 1.
2. Accept any number of parameters
(1) Accept any number of position parameters
The "*" expression can be used in function definitions to define a function that can accept any number of positional parameters, in addition to splitting iterative objects of any length we talked about in Chapter 1, as follows:
def avg(first, *rest):
print(rest)
return (first + sum(rest)) / (1 + len(rest))
print(avg(1, 2, 3, 4, 5))
# (2, 3, 4, 5)
# 1. 5
Parameters beginning with "*" must be used as the last position parameter, and the parameters beginning with "*" are tuple data structures after being passed in.
(2) Accept any number of keyword parameters
To accept any number of keyword parameters, we can similarly use
"**"
The parameter at the beginning of the. As shown below:
import html
def make_element(name, value, **attrs) -> str:
key_values = [ ' %s="%s"' % item for item in attrs.items()]
attr_str = ''.join(key_values)
# Perform a string formatting operation.
element = '<{name} {attrs}>{value}</{name}>'.format(name=name, attrs=attr_str, value=html.escape(value))
return element
res_1 = make_element('item', 'Albatross', size='large', quantity=6)
res_2 = make_element('p', '<spam>') # escape Will put here '<spam>' In '<' And '>' Replace it with a safe sequence < >
print(res_1) # <item size="large" quantity="6">Albatross</item>
print(res_2) # <p ><spam></p>
"**"
The parameter at the beginning must be used as the last 1 keyword parameter, and
"**"
The first parameter is passed in as a dictionary data structure.
(3) Accept any number of position parameters and keyword parameters at the same time
If you want a function to accept any number of positional and keyword arguments at the same time, just use the
"*"
And
"**"
That's enough.
def anyargs(*args:tuple, **kwargs:dict):
print(args)
print(kwargs)
anyargs(2, 3, 4, 5, time=1, data=2)
# (2, 3, 4, 5)
# {'time': 1, 'data': 2}
3. keyword-only parameters
As I said earlier,
"*"
The first parameter can only be used as the last position parameter,
"**"
The parameter at the beginning can only be used as the last keyword parameter (naturally, it is also the last parameter), and it is inferred that the parameter after the parameter at the beginning of "*" must be a keyword parameter.
# Appear in *args The following parameter is called keyword-only Parameter
# In these two examples, y They can only be keyword parameters, and must be guaranteed when transferring parameters key And formal parameter 1 Pathogenic
def a(x, *args, y):
print(y)
def b(x, *args, y, **kwargs):
print(y)
a(4, 6, 7, 8, y=1)
b(4, 6, 7, 3, y=1, data=2, year=3)
# 1
# 1
Such parameters are called
keyword-only
Parameter, that is, it appears in *
args
Subsequent parameters can only be used as keyword parameters.
We can take full advantage of this 1 property by placing keyword arguments after arguments that start with *, or after a separate *, forcing the caller of the function to pass keyword arguments, such as the following:
def recv(max_size, *, block):
'Receives a message'
pass
recv(1024, True) # recv2() takes 1 positional argument but 2 were given
# and missing 1 required keyword-only argument: 'block'
recv(1024, block=True) # OK
In real projects, this technique can be used to specify keyword parameters for functions that accept any number of positional parameters, such as the following minimization function with truncation. Here's
clip
Parameter is forced to be passed in as a keyword parameter, and a default value is set
None
Make the parameter optional. As shown below:
def mininum(*values, clip=None):
m = min(values)
if clip is not None:
m = clip if clip > m else m
return m
res1 = mininum(1, 5, 2, -5, 10)
res2 = mininum(1, 5, 2, -4, 10, clip=0)
print(res1, res2) # -5, 0
In addition,
keyword-only
Parameters can improve code readability, such as the following function writing:
msg = recv(1024, False)
If the reader of the code is not familiar with it
recv
Function works, so you may not quite understand the
False
It would be much clearer if the call to this function could be written as follows (of course, the writer of this function should force the user of this function to write this from the beginning):
complex(3, 5)
complex(*(3, 5))
0
Finally, if the function is defined when it is forced to use
keyword-only
Parameter, then when the user requests help information, the parameter information can naturally appear:
complex(3, 5)
complex(*(3, 5))
1
3. Optional parameters (parameters with default values)
To define an optional parameter, you need to assign a value to the parameter in the function definition and ensure that the default parameter appears at the end of the parameter list. Like this:
complex(3, 5)
complex(*(3, 5))
2
If the default value is a mutable container, such as a list, collection, dictionary, etc., you need to set the
None
As the default value: as follows:
def spam(a, b=None):
if b is None:
b = []
Warning 1: Never write directly like the following:
complex(3, 5)
complex(*(3, 5))
4
If you write as above, something you don't expect to see happens: If the default value is modified outside the function body, the modification will still haunt the subsequent function call, as shown below:
complex(3, 5)
complex(*(3, 5))
5
Warning 2: In the function body, we often need to judge whether the parameter is None. Here, we need to use the is operator. Never write it directly like the following:
complex(3, 5)
complex(*(3, 5))
6
The problem here is that although
None
Will be judged as
False
However, there are many other objects (such as strings of length 0, lists, tuples, dictionaries, and so on) that also have this behavior. In this way, many other specific inputs will also be judged as False, and then the value that should have been passed in by the user will be directly overwritten by the default []. As shown below:
complex(3, 5)
complex(*(3, 5))
7
Finally, let's discuss a very difficult problem. We want to detect in the function whether the caller supplied a specific value for the optional parameter (which can be arbitrary,
None
In this way, we can't use it naturally
None
,
0
,
False
Use them as defaults and then test them again, because users themselves may take them as parameters.
To solve this problem, you can write as follows:
_no_value = object()
def spam(a, b=_no_value):
if b == _no_value:
print("No b value supplied")
return
print(a, b)
spam(1) # No b value supplied
spam(1, 2) # 1 2
spam(1, None) # 1 None
Here
_no_value
Is based on
object()
Class, which can be used to detect the parameters provided by the user, because it is almost impossible for the user to put
_no_value
Object as parameter input (unless the user passes in the same object, even if it is
object
The other 1 object of type is the same as the
_no_value
Objects are different).
Here is a brief description of 1
object
Class,
object
Yes
Python
The base class for almost all objects in,
object
Object does not have any data (the bottom layer is missing
__dict__
Dictionary, can't even set any properties), its only function of 1 is to detect equality.