--This article is a partial excerpt from a particular chapter of the book "Getting Started with Python Programming" (https://github.com/simon-ritchie/python-novice-book-preview).
――Because it is an introductory book, it is for beginners.
--Mainly the contents of the function chapter.
--Please note that there are some parts that do not match the Qiita article (words such as "chapter" and "page" are used, the number of line breaks is extra, links do not correspond, etc.). I don't want to adjust it for Qiita because it's troublesome. </ s> If you are interested, please use the e-book version linked above.
――If you give us feedback in comments, we may use and reflect it on the book side as well.
In this chapter you will learn about Python functions. What is a function in the first place? It seems like that, but I will explain it including the explanation around that.
There are many benefits to using functions well, such as reducing the amount of code you write, avoiding writing the same code over and over, and making the code easier to read.
Let's start with the explanation of the function itself.
The function is function in English. There is something called a function in mathematics, which is also called a function in English, but the contents of the function are different between mathematics and programs. Please note that it is different.
Functions in Python programs have the following main characteristics.
--A certain amount of programs. --You can execute the program of the function from various places. --The behavior of the program in the function can be changed according to the received contents. --Any result can be returned depending on the contents of the function program.
Seki ** Number **, something related to numbers because it is attached to numbers? You might think that, but the function accepts various input other than numerical values, such as strings and lists. It's a little confusing in Japanese, but in English for functions, there are no words related to numbers, and just keep in mind that it is simply a function.
In addition to the meaning of a function, function also has the meaning of "function" and "work". It may be good to think of a program function as "a program with some function is executed" when it is executed.
To create a Python function, use the keyword def
. Put a half-width space after def
, write the name of the function after it, write the half-width (
and)
parentheses, and add the half-width colon:
at the end of the line. You can create a function.
It's like def function name ():
. Basically, half-width alphanumeric characters are used for the function name.
The contents of the function program will be written there by adding one indent (four half-width spaces) from the next line of the function defined by def
.
As a sample, if you want to set the function name to print_one_plus_one
in the program content of the function that prints the contents of 1 + 1 with print, the code is as follows.
def print_one_plus_one():
print(1 + 1)
In the indentation section of the previous chapter, I explained that "indentation represents the hierarchical structure of the program" and "the more to the right, the deeper the program hierarchy".
Even in function programs, this rule that "the program hierarchy is deeper toward the right" is still alive.
Let's pay attention to the part called print (1 + 1)
where one indent (4 half-width spaces) is set in the above code.
This part corresponds to "program in function". In other words, the program hierarchy has become deeper due to the increase in indentation, such as "program calledprint (1 + 1)
" in "function called print_one_plus_one" (the program is included by the amount of indentation). Masu).
Also, in the section on indentation in lists and dictionaries, I explained that even code that omits indentation as follows will work (it will not cause a program error).
int_list = [
1,
2,
3,
4,
]
On the other hand, indentation has ** meaning ** in functions. "The start position of the program with indentation" means "the start position of the program in the function", and "the position immediately before the program without indentation" means "the end position of the program in the function". I feel that this area is a little difficult to understand, so I will take a closer look based on the program.
Keep in mind that the function program will not work unless you set the correct indentation for the time being.
As a test, let's write and execute the code without indentation after the function.
def print_one_plus_one():
print(1 + 1)
File "<ipython-input-12-a31292ca450b>", line 2
print(1 + 1)
^
IndentationError: expected an indented block
As mentioned above, if there is no indent after the function, an error will occur. IndentationError is an error caused by incorrect indentation, indented block means a block of indented code, expected means "expected", so "it is assumed that the code part with added indentation will come." I get an error message like "It's done, but it's not (no indentation)".
Note that if the line is not code, for example, just an empty line (a line where no program is written), there is no problem even if there is no indentation. For example, it doesn't matter if there is an empty and unindented line between the line digit_value = 1 + 1
and the lineprint (digit_value)
as shown below.
def print_one_plus_one():
digit_value = 1 + 1
print(digit_value)
To finish the function, write the code without indentation. For example, the contents of a function will not be executed unless the function is executed (described in the next section), but in the following code, the part print (3 + 5)
has no indent (= function). Since the contents of) are finished), it is executed immediately without calling the function, and the result of 8 is displayed.
def print_one_plus_one():
digit_value = 1 + 1
print(digit_value)
print(3 + 5)
Output contents of code execution result:
8
To call (execute) the created function, use half-width (
and )
parentheses after the function name, such as function name ()
.
If you want to execute the function print_one_plus_one
that you created a while ago, write something likeprint_one_plus_one ()
. When you run the code, you can see that the program inside the function (print (1 + 1)
) is executed and 2 is output.
def print_one_plus_one():
print(1 + 1)
print_one_plus_one()
Output contents of code execution result:
2
Variables created in a function behave specially.
For the sake of explanation, first write and execute the following code.
def print_one_plus_one():
digit_value = 1 + 1
print(digit_value)
print_one_plus_one()
digit_value += 1
2
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-21-50561b28b02f> in <module>
5
6 print_one_plus_one()
----> 7 digit_value += 1
NameError: name 'digit_value' is not defined
The print_one_plus_one
function is executed first (print_one_plus_one ()
), where a variable called digit_value
is created (digit_value = 1 + 1
), and then 1 is added to the variable of digit_value
outside the function. The code is (digit_value + = 1
).
However, when I executed it, I got an error message ( name'digit_value' is not defined
) saying "The variable named digit_value
is not defined ".
Why are you creating variables in the code inside the function?
In fact, variables created inside a function basically disappear when the function finishes executing. Therefore, if the variables created in the function are left as they are, they cannot be used (often referred to) from the code outside the function (the part without indentation) or from other functions.
Imagine that there are various variables in a box called a function. Another function will be another box. Each other, you can only use variables that are in the box.
The range of variables that can be referenced like this box is called ** scope **. In English, it is scope. It is a word that means "range" or "field of view". In programming, it means "accessible range of variables, etc."
Let's take a closer look at scope.
Earlier, when I tried to access a variable inside a function outside the function, I got an error. What happens if you access a variable created outside the function from inside the function?
References of variables created outside the function within the function behave differently depending on the type of the variable.
First, let's try an integer (int) variable as an example.
int_variable = 100
def add_one():
int_variable += 1
add_one()
UnboundLocalError Traceback (most recent call last)
<ipython-input-4-e73c01cb25ac> in <module>
6
7
----> 8 add_one()
<ipython-input-4-e73c01cb25ac> in add_one()
3
4 def add_one():
----> 5 int_variable += 1
6
7
UnboundLocalError: local variable 'int_variable' referenced before assignment
When I try to run it, I get the above error. Unbound has the meaning of "unbound" or "unassigned" in addition to the meaning of "unbound".
In addition, variables in functions are called local variables (local variables in English). A rule only for a specific region is called a local rule, but a local variable has a similar feeling and means "a variable only in a specific function".
referenced means referenced, and assignment means something like an allocation. Here, there is no problem if you read it as if the variable has not been created.
Therefore, the error message local variable'int_variable' referenced before assignment
becomes the message" The local variable ʻint_variable` is referenced before creation. "
There is a global variable that is paired with a local variable. While local variables can only be referenced by specific functions, global variables can be referenced in various places depending on the settings.
If you create a variable outside a function, it becomes a global variable. Actually, the variables that we have created before the function chapter correspond to global variables.
In the code that resulted in UnboundLocalError mentioned above, the global variable is created first with the code ʻint_variable = 100`. He also explained that global variables can be referenced in various places.
In that case, isn't it strange that an error occurs when referencing ʻint_variable in the ʻadd_one
function? Isn't it strange that local variables are displayed in error messages even though they are global variables? You may feel that.
The reason for this behavior is that the Python program does not know "is this a local variable?" Or "is it a global variable?".
You can use the same name for global variables and local variables. Therefore, if this is left as it is, the program cannot determine which one should be handled, and the local variable handles integers. If you want to handle global variables such as integers, you need to explicitly tell the program "This is a global variable".
To tell the program that a particular variable is a global variable, write global variable name
in the function. If you treat the variable ʻint_variablein the above code as a global variable, it will be in the form
global int_variable`.
If you rewrite it so that the error does not occur, it will be as follows. You can confirm that 101 is output by adding 1 to the value of the global variable 100
.
int_variable = 100
def add_one():
global int_variable
int_variable += 1
print(int_variable)
add_one()
Output contents of code execution result:
101
What happens if you use global
inside a function and then create a variable before creating a variable outside the function (global variable) in advance, and then refer to that variable outside the function after executing the function?
Let's write the code and run it.
def define_global_variable():
global int_variable_2
int_variable_2 = 200
define_global_variable()
print(int_variable_2)
Output contents of code execution result:
200
This time, the new variable name is ʻint_variable_2. The function is executed in the
define_global_variable () part, variables are created as global variables inside the function (
global int_variable_2 and ʻint_variable_2 = 200
), and then the variable is referenced (output) outside the function. (Print (int_variable_2)
).
You can see that what was an error when there was no description of global
can output the contents of the variable 200 without an error.
In the previous section, we confirmed that trying to access a global variable such as an integer as it is in a function results in an error.
This behavior is the same for non-integer strings (str), floating point numbers (float), boolean values (bool), and other types of values.
On the other hand, the behavior changes for values such as lists and dictionaries. Let's see how they differ one by one.
First, create a global variable outside the function and refer to that variable inside the function (without the description of global).
dict_variable = {'name': 'orange'}
def print_dict_variable():
print(dict_variable)
print_dict_variable()
Output contents of code execution result:
{'name': 'orange'}
I'm creating a dictionary global variable outside the function (dict_variable = {'name':'orange'}
) and executing the function (print_dict_variable ()
). Inside the function, the contents of the global variable of the dictionary are output (print (dict_variable)
).
When I tried with an integer variable in the previous section, I got an error if I did not specify the variable with global
(it was judged that the local variable was not generated) in this way of writing, but in the dictionary In the case of a global variable, you can see that no error occurs even if you do not specify it with global
, and the value can be output properly.
In this way, you can refer to global variables in functions even in dictionaries and other lists. Please note that the behavior of the scope is different from that of integers.
Next, let's check the behavior when a local variable is created in the function with the same variable name as the global variable (the specification of global
is omitted).
dict_variable = {'name': 'orange'}
def change_dict_variable():
dict_variable = {'name': 'apple'}
change_dict_variable()
print(dict_variable)
Output contents of code execution result:
{'name': 'orange'}
First, create a global variable in the dictionary (dict_variable = {'name':'orange'}
), and then execute the function (change_dict_variable ()
). Inside the function, we are creating a new dictionary variable with the same name as the global variable (dict_variable = {'name':'apple'}
). Finally, the contents of the global variable are printed outside the function (print (dict_variable)
).
As you can see from the output result ({'name':'orange'}
), the value set in the function ({'name':'apple'}
) is not reflected and it is a global variable. The value at the time of making is the same.
This means that when you create a new list or dictionary in a function, even if there is a global variable with the same name, it will be treated as a local variable. In other words, when the contents of the function are executed, the contents of the local variable disappear, and as a result, the value of the global variable remains as it is.
It's a little complicated. Even if you can't remember everything, it's okay if you can remember it each time you need it by running the code and trying it out. Just keep in mind that the behavior of the scope changes depending on the conditions.
Finally, let's try the behavior in the case of setting a new dictionary by creating a global variable of the dictionary in advance and specifying the variable with the same name using global in the function.
dict_variable = {'name': 'orange'}
def change_dict_variable():
global dict_variable
dict_variable = {'name': 'apple'}
change_dict_variable()
print(dict_variable)
Output contents of code execution result:
{'name': 'apple'}
Only the global dict_variable
part in the function has been added compared to the previous code. However, due to this description, the variable of dict_variable
is treated as a global variable instead of being treated as a local variable, so the result of the output processing (print (dict_variable)
) after executing the function is{'name':'orange'}. It has changed to
{'name':'apple'}(value set in the function) instead of
(value when global variable is set).
In this way, the behavior changes depending on the value type and whether or not global is specified. It's complicated, so the following ideas can help keep it simple.
--Do not use global variables, or minimize them even if they are used (the arguments are mainly used because there are many cases where they can be replaced by the function ** arguments ** that will be mentioned later). --If you want to treat it as a global variable, specify it in global regardless of the numerical value or dictionary (do not omit it in the dictionary etc.). --Avoid using the same name for global variables and local variables when it seems confusing (it seems to cause problems).
Also, as an index, although it is not a strict definition, it is not a strict definition to determine whether global is required for referencing global variables in a function for each type.
--Global must be specified for a single value (integer, string, etc.) --Global can be omitted for large values (lists, dictionaries, etc.) that store many single values.
It may be easier to understand if you remember about it.
Of course, you can realize a program that works even if you write the code as it is without providing a function. So why bother to use a function?
There are various reasons, but the two main ones are "to reduce code duplication" and "to make the code easier to read".
The code samples up to this point are all short code, so it may be difficult to understand the benefits.
However, in real-life work, we often deal with long programs and programs with many files. The benefits of functions come to life in such complex environments.
For example, let's say you write about 20 lines of code at work. At this level, nothing matters.
However, similar processing will be required in the future, and 40 lines will be doubled, and it will increase to 60 lines ... While repeating, hundreds, thousands, tens of thousands of lines. .. will be. This is especially true for projects that last for years.
If you write the same code every time, it will be difficult to grasp the code. Since the number of variables becomes huge, it becomes difficult to follow the code such as "How is this variable used?", And it is difficult to operate unrelated variables. Many mistakes will occur.
Also, suppose that the processing required in the future changes and you need to edit the code. If there are dozens of similar codes, it will be very difficult to change the code without making a mistake. If any one of the changes is missing, it will result in a bug (also called a bug) or an error.
The job of writing a program requires frequent updates and additions of features, so this can be a pain.
On the other hand, what if the processing executes the function and the code of the actual processing is written in the function?
Since you only have to change the code in the function, you can prevent omission of changes. It also requires very little work to make changes.
By making good use of functions in this way, you can reduce the time and risk required for changes by making the duplicated processing part of the code into a function.
Another big advantage is that the code is easier to read, depending on how you use the function.
When reading a program, the fewer elements it has, the easier it is to read. For example, if the code has about 300 variables and there are many conditional branches that will appear in later chapters, it will be very difficult to grasp the contents accurately and it will be easy to make mistakes.
On the other hand, as mentioned in the scope of the previous section, functions have the property that local variables are "used only within the function" and "the local variables disappear when the function ends".
This property makes the code very readable, for example, if you divide a process that requires 300 variables into many functions and then subdivide it into 5 or so per function.
I often hear stories like "humans can remember about 3 to 9 elements at a time", but the same is true for programs, and if there are many elements at once, it becomes difficult to grasp and remember for a short period of time. ..
It may be close to making it easier to understand by inserting hyphens in 3 numbers or 4 numbers in the telephone number etc. By splitting by function and reducing the number of variables and processes per function, you can make the code easier to understand and less likely to make mistakes like splitting a phone number.
In addition, there is an advantage that it becomes easier to write a test by dividing it into many functions with less processing. The test etc. will be quite advanced, so I will explain it in detail in a later chapter.
Creating a function using variable values, such as variables, is more versatile and easier to use than processing a function using only fixed values.
For example, there are more cases where the corresponding function can be used by "calculating x by 3" with an arbitrary value of x than by "calculating 5 x 3".
You can use any variable by using the global variables mentioned in the previous section, but in such cases, it is common to use a function called "argument" of the function. The argument is called argument in English.
Although it is named subtraction ** in Japanese, it accepts non-numeric arguments in the program. You can specify various arguments such as character strings, boolean values, and lists.
In addition to the meaning of an argument, the English argument also has the meaning of "argument" and "argument", as can be expected from the English word of argue, which means "discuss" and "argue".
At first glance, the arguments and the argument seem to have nothing to do with each other, but in the original sense, they are derived from the "rationale (reasons and evidence to support the argument)" and "to seek other quantities." It seems that it comes from the fact that it has changed in such a way as "the original amount used for".
Given the property that the result of function processing fluctuates depending on the value of the argument, the word argument also comes a little nicely.
The word argument in Japanese may be close to something like "value to pass to a function" in terms of meaning.
You can pass any value to the function by using arguments.
The passed arguments are treated as local variables of the function. Since the previous section has the property that "local variables are used only within the function" and "local variables disappear when the function is finished", the code is easier to read and less likely to make mistakes than writing code using many global variables. You can write.
In the sample code so far, we have created a function that does not use any arguments.
To create a function that accepts arguments, specify the argument names in the (
and )
parentheses after the function name.
For example, in the above-mentioned process of "calculating x to be multiplied by 3 with an arbitrary value of x", write def multiply_three (x):
to create a function named multiply_three that accepts x as an argument. I will.
To specify the value of the argument when executing the function, set the value you want to specify for the argument in the parentheses of (
and )
instead of writing multiply_three ()
. For example, if you want to specify 10 as an argument, write multiply_three (10)
.
Let's actually write the code, execute the function and check the result.
def multiply_three(x):
multiplied_value = x * 3
print(multiplied_value)
multiply_three(10)
Output contents of code execution result:
30
The function is executed in the multiply_three (10)
part, and 10 is specified as an argument. In the function (def multiply_three (x):
), the value of x given to the argument (since it is the value specified at runtime, x is 10 this time) is tripled ( multiplied_value = x * 3
).
Finally, the tripled value is output by print. The output result is 30 which is 3 times 10.
Earlier, I created a function that triples the value of x with the argument x. Now let's change the value of "multiply" by the argument at runtime. Accept the argument y instead of the triple part.
To specify the second and subsequent arguments, add a half-width comma between the arguments. It doesn't cause an error even if you don't put a space, but since it is stipulated in the Python coding standard to put one half-width space after the comma, write it like that.
The argument part of the function in this case is code like (x, y)
.
def multiply_x_by_y(x, y):
multiplied_value = x * y
print(multiplied_value)
multiply_x_by_y(10, 5)
Output contents of code execution result:
50
When executing a function with multiple arguments, set the values there as well, separated by commas. If you want to set x to 10 and y to 5, write the function execution part like multiply_x_by_y (10, 5)
.
In the processing inside the function, the code is multiplied by y instead of the code that is tripled like * 3
(multiplied_value = x * y
).
As a result, the value output by print by multiplying 10 of x and 5 of y is 50.
If you want to use 3 or more arguments, you can set any number of arguments by adding commas. For example, if you want to create a function that takes three arguments x, y, z, write as follows.
def multiply_x_y_z(x, y, z):
multiplied_value = x * y * z
print(multiplied_value)
multiply_x_y_z(10, 5, 3)
Output contents of code execution result:
150
The argument part has three values, (x, y, z)
, and even when executing the function, three values are specified, such as multiply_x_by_y (10, 5, 3)
, separated by commas. I will.
The output result by print is 150 with 10 x 5 x 3 of the three arguments of xyz.
In this way, multiple values can be set for the argument, but they are called as the first argument, the second argument, the third argument, and so on, respectively. In this function, the first argument of the multiply_x_y_z
function is x
, the second argument is y
, and the third argument is z
.
For example, what happens if you specify only two values at runtime in a function that accepts three arguments? Write the code and give it a try.
def multiply_x_y_z(x, y, z):
multiplied_value = x * y * z
print(multiplied_value)
multiply_x_y_z(10, 5)
The content of the code is a function that accepts three arguments x, y, z
, and at runtime it passes only two values as arguments, such asmultiply_x_y_z (10, 5)
(value of the argument of z). Is not specified).
TypeError Traceback (most recent call last)
<ipython-input-27-8cab8c50c583> in <module>
4
5
----> 6 multiply_x_y_z(10, 5)
TypeError: multiply_x_y_z() missing 1 required positional argument: 'z'
When I tried it, an error occurred. Let's read the error message.
Missing means "not enough" and required means "required". argument was an English word for the argument.
Roughly translated, the error message is "There are not enough arguments in the required (non-missable) position named'z'".
An error will occur if the required arguments are not specified when the function is executed in this way. If you get this error, check "What arguments are missing" and check the code you are running to see if the number of arguments is correct.
As you can see from the error message in the previous section that says required positional argument
and the error message is a required argument, you can also set the" non-required (optional) "argument.
These optional arguments are called "optional arguments" (optional arguments in English).
Also, if omitted, "what value the argument will be" is specified by what is called the "default value". To set the default value for the argument, set the half-width equal =
symbol immediately after the argument name and the default value you want to set. For example, if you want to set the default value of 10 for the argument x, write x = 10
.
When creating variable settings, half-width spaces were inserted before and after the equal, but the correct Python coding convention is not to insert spaces before and after the equal in the default argument. Please note that it is different from variable settings.
Even if you insert a space, no error will occur, but the code will not comply with the coding standards.
Write the code and give it a try.
def print_x(x=10):
print(x)
The content is a simple function that just prints the value specified in the argument with print. There is only one argument named x.
Make sure that the argument part is x = 10
. This is the description that "if the argument specification of x is omitted, the default value of 10 is set".
Let's execute the function. First, let's execute it without omitting the argument of x. Specify 30 for the x argument.
print_x(30)
Output contents of code execution result:
30
The value of 30 specified in the argument was output.
In this way, if you specify the value without omitting the argument for which the default value is set, you can see that the specified value has priority (30 this time) and the default value of 10 is ignored.
This time I will omit the argument and execute it. Notice that there is nothing between the parentheses of (
and )
(the value of the argument is not specified).
print_x()
Output contents of code execution result:
10
As a result, 10 which is set as the default value of the argument is output.
In this way, when the default value is set as an argument,
--When a value is specified for the argument-> The specified value is set. --If the argument is omitted-> The default value of the argument is set.
It becomes the behavior.
The default value is used mainly in cases such as "usually this default value is okay, but you want to change the value once in a while".
On the contrary, the default value should not be set in the case where the value specified for the argument is basically different every time.
In such cases, the function should be created in such a way that normal arguments are required. If you need to specify the argument every time, but you forget to specify it, if the default value is set (even if you forget to specify the argument), an error will not occur and you may not notice the mistake. Because it can be done.
Also, when setting an argument with a default value, there is a rule that "the argument for which the default value is set must come after the required argument".
For example, if you set an argument with a default value (x = 10
) followed by a required argument without a default value (y
) in the function as shown below, an error will occur.
def multiply_x_by_y(x=10, y):
multiplied_value = x * y
print(multiplied_value)
File "<ipython-input-34-13a53a0612f1>", line 1
def multiply_x_by_y(x=10, y):
^
SyntaxError: non-default argument follows default argument
If you translate the error message, it will be something like "arguments that do not have default values come after arguments that have default values".
This is because when you execute a function such as multiply_x_by_y (10)
, the first argument can be omitted while the second argument cannot be omitted (there is no default value), so (10) This is because the program cannot determine whether the value of)
is the value for x in the first argument or the value for y in the second argument.
Therefore, the argument with the default value must be placed after the required argument. As shown below, if you set two arguments, x and y, the x side is a required argument and the y side is an optional argument with a default value, it works without error.
def multiply_x_by_y(x, y=10):
multiplied_value = x * y
print(multiplied_value)
In the case where this error does not occur, if you specify only one argument such as multiply_x_by_y (30)
and execute it, you can see that it is the value for x of the required first argument, and multiply_x_by_y (30, 20) Even if you specify both values without omitting
and the argument, the code can be interpreted by the program without any problem, such as the value of x is 30 and the value of y is 20.
Even if there are multiple required arguments, the argument with the default value must come after them.
For example, as shown below, it is not possible to set the required argument z after the required argument x followed by the argument y with the default value (an error will occur).
def multiply_x_y_z(x, y=20, z):
multiplied_value = x * y * z
print(multiplied_value)
File "<ipython-input-39-81a253f339fe>", line 1
def multiply_x_y_z(x, y=20, z):
^
SyntaxError: non-default argument follows default argument
Even if there are multiple required arguments like this, the argument with the default value (z = 20
) must be brought after the required argument without the default value as shown below.
def multiply_x_y_z(x, y, z=20):
multiplied_value = x * y * z
print(multiplied_value)
Even if you want to set multiple arguments with default values, no error will occur if they come after the required arguments. For example, if you want to set the y and z arguments to have default values, no error will occur if each of them follows the required argument x that does not have a default value as shown below.
def multiply_x_y_z(x, y=20, z=30):
multiplied_value = x * y * z
print(multiplied_value)
For example, suppose you have a function with many arguments:
def calculate_cost(manufacturing_cost, labor_cost, delivery_cost, tax):
sum_value = manufacturing_cost + labor_cost + delivery_cost + tax
return sum_value
When I try to execute the function, it looks like this:
calculate_cost(1000, 400, 150, 50)
With this number, you can understand which argument each value corresponds to. However, it feels difficult to understand, and it is likely that you will inadvertently make a mistake in the order.
What if the number of arguments increases further? Imagine, for example, a function that requires 10 arguments, or a function that requires 15 arguments.
It seems to be very difficult to specify the argument values in order without making a mistake. Also, imagine the case where the function frequently changes the number of arguments with updates. If there are no arguments in the middle, the order of the arguments after that will be out of order, which is very confusing.
As a countermeasure for such cases, Python has a function called "keyword arguments (keyword arguments in English)".
By using keyword arguments, you can write easy-to-read code even for functions with many arguments.
Let's actually write the code for the function execution part. To use keyword arguments, you can use them by writing them in the form argument name = value specified in the argument
at the function execution location. For example, in the function of the sample code above, to use the keyword argument with the argument of manufacturing_cost
, write manufacturing_cost = 1000
.
When specifying multiple other functions, the rule of separating them with a single-byte comma is usually the same as the argument specification.
calculate_cost(
manufacturing_cost=1000,
labor_cost=400,
delivery_cost=150,
tax=50)
By using keyword arguments, you can immediately see which argument the value of each argument is. For example, delivery_cost
is 150.
Also, if you use keyword arguments, the code for the argument name becomes long horizontally and it becomes difficult to read, so in the above code, a line break is inserted for each argument.
As mentioned above, keyword arguments have several merits in addition to the merits of "a function with many arguments makes it easier to understand the contents and makes mistakes less likely".
For example, it is useful in a function that has many arguments with default values, such as "I want to set a specific value for only some of the arguments at the end".
Suppose you have a function like this:
def multiply_x_y_z(x=10, y=20, z=30):
multiplied_value = x * y * z
print(multiplied_value)
This function has default values for all x, y, and z arguments (arguments can be omitted).
Let's assume that this function needs to change only the argument of z to a value of 100. If you specify a normal argument, you have to specify the values in order, so if you try to specify the value of z, you have to specify the same value for x and y as the default value (multiply_x_y_z (10, 20, 100) )
).
If there are about 3 arguments, it will become painful as the number of arguments increases. Especially in cases where the latter argument is used more frequently, it becomes more painful (even if the arguments are set in order of priority at the time of writing the code, it will be behind due to the passage of time or updates etc. It is possible that the argument of is more important).
And what if the code is updated and the default value of the function changes? For example, suppose the default value of a function is updated to def multiply_x_y_z (x = 100, y = 200, z = 300):
.
In such a case, if the function execution side (code such as multiply_x_y_z (10, 20, 100)
) is not updated without omission, it is said that "the same value as the default value was assumed and specified". In some cases, it may behave unexpectedly (if there are many places where the function is executed, it will be troublesome to fix it without mistakes).
On the other hand, keyword arguments allow you to execute a function by directly specifying a value only for the argument with a specific argument name.
For example, if you want to specify the value only for the argument of z and set the other values as the default values, you can write as follows.
multiply_x_y_z(100)
By writing this way, you can reduce the extra description, and you can reduce the effect when the default value is changed in the function.
Another point to consider with keyword arguments is that "arguments that take default values should basically be specified as keyword arguments."
Regarding the argument that takes the default value, due to the property that the setting is arbitrary (it does not have to be), it may be added or deleted due to daily updates, or the order of the arguments may be changed. There are cases to do.
Therefore, basically, if you specify the argument with the default value as a keyword argument every time, it will be hard to be affected and the code will be robust so that it is okay if the order of the arguments with the default value changes.
Shouldn't we change the referenced function? You may think that, at work, I often use libraries made by other people (like a convenient and general-purpose code collection), but such libraries are old for security reasons. In some cases, you will have to update because the support has expired in the version.
In such cases, use keyword arguments appropriately to reduce the number of things that get stuck in the update or cause bugs.
It's a bit like the difference in behavior between global and local variables for each type mentioned in the previous section, but the arguments also have the concepts of "passing by value" and "passing by reference".
Although it is a little difficult to understand the meaning of Japanese, each has the following characteristics.
--Pass by value of argument-> The value of the variable specified in the argument is copied and passed. Therefore, updating the variable inside the function does not affect the variables outside the function. --Passing the argument reference by value-> Values such as variables specified in the argument are not copied. Therefore, if you update the value inside the function, the contents will change even for variables outside the function.
Depending on the type of value, the behavior is divided into passing by value and passing by reference.
--Integers (int), floating point numbers (float), strings (str), boolean values, etc.-> Pass by value --Dictionaries, lists, etc.-> Passing by reference
It will be.
It's hard to understand, so let's write the code and try it.
First, let's try the case of specifying an integer as an argument, which is passed by value.
def add_one_to_x(x):
x += 1
cat_age = 10
add_one_to_x(x=cat_age)
print(cat_age)
Output contents of code execution result:
10
First, we are creating a variable named cat_age
outside the function. The value is set to 10.
After that, the function is executed in the ʻadd_one_to_x (x = cat_age) part, and the variable
cat_age` is specified as the argument value.
In the function, 1 is added to the argument value, and finally the variable value is output by print (cat_age)
.
The output result is 10 (not 11) even though 1 is added in the function.
The variable cat_age
specified in the argument this time is an integer value. Therefore, it is passed by value, and in passing by value, the value is copied and passed to the function (passed as something different from the original variable), so even if the value is updated in the function, the original variable will be affected. It remains at 10 without.
Now let's try writing a code for a case where the reference is passed by value. Earlier I specified an integer value as an argument, but this time I specify a dictionary as an argument.
my_age = 25
my_age += 2
print(my_age)
Output contents of code execution result:
27
First, I set a dictionary with the key ʻage in the variable
cat_info_dict`.
After that, the function is executed and the variable cat_info_dict
is specified as an argument.
In the function, 1 is added to the value of the ʻage` key of the dictionary specified in the argument.
Finally, print prints the contents of the cat_info_dict
variable.
As you can see from the output result, the update of the dictionary value executed in the function is also reflected in the original variable, and it can be seen that the result of the ʻage` key of the dictionary is 11. I will.
When a dictionary or list is specified in this way, it is passed by reference, and the original variable is also changed.
Since the behavior changes depending on the type, there are both cases where the variable is expected to be updated but is "updated" and the variable is expected to be updated but is not updated. Be aware that mistakes are likely to occur inadvertently.
By the way, why does the behavior change depending on the type like this? There are two main reasons, and the first is that "basically, like local variables, mistakes can be reduced if there is no effect outside the function."
As mentioned in sections such as local variables and global variables, local variables disappear after the function has finished executing. Therefore, it is safer to handle the code in terms of making mistakes less likely, such as a lot of variables being created in the area outside the function and not being able to be referenced by other functions.
When an integer or character string is passed by value, it is treated in the same way as a local variable. In other words, when the function finishes executing, the value specified in the argument (the value copied from the original variable, etc.) is discarded.
This allows for a secure implementation just like dealing with local variables.
So why are lists and dictionaries passed by reference, not copied, but as arguments? Why is it safer to copy and treat it as a local variable?
The reason is that lists and dictionaries can store a lot of numbers and character strings, so if you copy them, the processing load will increase.
For example, what if the list contains millions of numbers? If the list is copied every time the function is executed, the processing time will be long, and if many such large lists are copied, a lot of memory of the personal computer will be required (specification). It will be difficult to execute the code on a low computer).
Therefore, in order to reduce the load when executing a function, in the case of a list or dictionary, the value of the variable is passed as it is without being copied by value. The fact that the value is passed to the argument without being copied in this way is the second advantage that the function can be executed with less load.
With that in mind, isn't it better to pass the numbers and character strings without copying them? However, even if the numerical value or the value of a single character string is copied, it is a load that can be said to be almost an "error" on a recent personal computer (except when a character string that is too long is specified). ).
If the load is that much, it is safer to copy the value and treat it like a local variable, so the value is copied as a value pass.
For this reason, the behavior of passing by value and passing by reference differs depending on the type based on the advantages and disadvantages.
If you get confused, you will make mistakes, so be careful.
However, it is a concept that is difficult to understand until you get used to it, so there is no problem if you learn these as you get used to programming little by little. As long as you keep writing the code, you'll probably experience "not behaving as expected" by passing by value in the future or by reference.
By gaining such experience, you will gradually and naturally remember it. Prioritize writing code without rushing.
In the previous pass-by-value section, I wrote that values such as integers and strings of arguments are copied and passed, and changes in those values inside the function are not reflected outside the function.
However, there are many cases where you want to receive the result of a function and set it in a variable outside the function.
In such a case, it can be realized by using the function called return value (also called return value or return value) of the function. The return value is the return value in English.
When setting the return value in a function, write something like return return value
in the function.
Let's actually write the code and move it. In the code below, the return added_value
part in the function is the description of the return value relationship.
def add_one(x):
added_value = x + 1
return added_value
returned_value = add_one(x=10)
print(returned_value)
Output contents of code execution result:
11
When you execute a function that has a return value set, the value will be returned. You can get the contents of the returned value by setting the value in a variable or the like.
In the above code, the part of returned_value = add_one (x = 10)
is applicable. ʻAdd_one (x = 10) The function is executed in the part, and the value is returned, so it is possible to get the value of the return value set in the function by the description that sets the value to the variable
returned_value = `. I can do it.
The content of the function is just to add 1 to the value specified in the argument x and return that value (return added_value
).
If you try to output the value of the return value (print (returned_value)
), you can see that 11 is output as the result of adding 1 in the function.
In addition to setting the return value, the description of return
also has the meaning of" stopping the processing of the function ". If the return
part is encountered in the function, the processing of the function is stopped there and the subsequent processing is not executed.
If you only want to stop the process, you can write only return
without setting the return value.
For example, if there is a description of return
just below the function as shown below, the subsequent processing will not be executed.
def add_one(x):
return
added_value = x + 1
return added_value
returned_value = add_one(x=20)
print(returned_value)
Output contents of code execution result:
None
Since there is a description of return
at the beginning of the function, the subsequent processing is not executed. Processing stops at that return
point.
In other words, the subsequent processing of ʻadded_value = x + 1 and
return added_value` will not be executed.
Even if you actually execute the function (returned_value = add_one (x = 20)
) and output the result (print (returned_value)
), the result of plus 1 is not output and the content is None. It is output. None is a value like "nothing", which we will discuss in more detail in later chapters. Since the processing is stopped without setting the return value only with return
, the return value is None.
The calculation result etc. are not returned, and you can see that the part such as return added_value
is not executed.
In the current situation, what is the control to stop the processing of such a function in the middle? Although it seems like that, it is useful for conditional branching that will be learned in later chapters. For example, you will be able to control things like "stop processing under XX conditions".
You can set multiple values for the return value. In that case, set multiple values separated by commas.
For example, in the code below, multiple return values are set separated by commas in the part return added_x, added_y
.
def add_one(x, y):
added_x = x + 1
added_y = y + 1
return added_x, added_y
returned_x, returned_y = add_one(x=100, y=200)
print('returned_x:', returned_x, 'returned_y:', returned_y)
Output contents of code execution result:
returned_x: 101 returned_y: 201
The content of the function is that it receives two arguments x and y, adds 1 to each, and returns both as return values.
As you can see from the part returned_x, returned_y = add_one (x = 100, y = 200)
, the part of the value to be set in the variable after executing the function must also be set separated by commas.
Finally, the contents of the returned value are printed by print (print ('returned_x:', returned_x,'returned_y:', returned_y)
).
As we'll see in more detail in later chapters, print can also print multiple values at the same time, separated by commas (print a total of four values to print two strings as labels and the values of two variables. Specified).
If you check the output contents, you can check the value specified for the arguments x and y plus 1 in each return value variable.
Setting the return value of multiple values is convenient, but just as it is easy to make mistakes if you try to use many arguments with normal arguments instead of keyword arguments, it is easy to induce mistakes if there are many return values. Unlike the argument side, there is no function such as keyword return value, so let's use it moderately so that it does not increase too much.
Importance: ★★ ☆☆☆ (You don't have to know at first)
Suppose you have a function (ʻadd_three_value) that takes three arguments, x, y, and z, as in the code below. I also have a list variable (ʻargument_list
) that stores three values, and I want to specify these variables in order.
def add_three_value(x, y, z):
total = x + y + z
return total
argument_list = [10, 20, 30]
Since each of the three values of the argument must be specified as an integer, the number of arguments does not match just by specifying the list as it is (only one argument is specified and the remaining two arguments are not enough. ) Will result in the error.
add_three_value(argument_list)
TypeError: add_three_value() missing 2 required positional arguments: 'y' and 'z'
In the case where you want to specify the value in the list for each argument like this, as a special way of writing Python, set the half-width asterisk *
symbol immediately before the variable in the list by specifying the value at the time of function execution. Then, the contents of the list will be assigned to the arguments in order.
In the code sample below, the code part * argument_list
is applicable.
returned_value = add_three_value(*argument_list)
print(returned_value)
Output contents of code execution result:
60
This time it is working without error. Also, if you look at the output, you can see that x, y, and z are passed 10, 20, and 30 of the contents of the list, respectively, and a total of 60 values are returned.
In this writing method using an asterisk, the contents of the list are expanded and assigned to the arguments, so if the number of arguments and the number of values in the list do not match, an error will occur.
For example, if you specify a list containing 4 values for a function that receives 3 arguments as shown below, an error will occur.
def add_three_value(x, y, z):
total = x + y + z
return total
argument_list = [100, 200, 300, 400]
add_three_value(*argument_list)
TypeError: add_three_value() takes 3 positional arguments but 4 were given
Looking at the error message, it says something like "The function add_three_value () requires 3 arguments, but 4 values are specified", and the number of argument of the function and the actual You can see that an error has occurred due to a mismatch in the number of values specified in.
However, if the default values mentioned in the previous section are set and include optional arguments, it does not matter if the number of arguments and the number of values in the list do not match. As shown below, in a function that has three arguments x, y, and z, if the default value is set for z (z can be omitted), the number of items in the list may be 2 or 3, and an error will occur. (Since 2 items cannot be omitted, an error will occur if a list with 1 value is specified).
The list can be handled by specifying one asterisk. But what about keyword arguments? For example, in the following case, you want to specify a dictionary with argument names set in the keys for a function that has three arguments x, y, and z as before.
def add_three_value(x, y, z):
total = x + y + z
return total
argument_dict = {
'x': 10,
'y': 20,
'z': 30,
}
If you want to specify a value in Python as a keyword argument using such a dictionary, you can handle it by setting two half-width asterisk symbols immediately before the argument value at the time of function execution. Put two asterisks in front of the dictionary, for example ** argument_dict
.
total = add_three_value(**argument_dict)
print(total)
Output contents of code execution result:
60
Even with the method of specifying keyword arguments using this dictionary, an error will occur if the keyword arguments are not specified sufficiently except for the arguments for which default values are set, as in the case of the list. For example, if you try to execute the code in the above function without the keyword argument of y included in the dictionary, the following error will occur.
def add_three_value(x, y, z):
total = x + y + z
return total
argument_dict = {
'x': 10,
'z': 30,
}
add_three_value(**argument_dict)
TypeError: add_three_value() missing 1 required positional argument: 'y'
Normally, an error will occur if you specify more values than the number set in the function as arguments, as in the case where 3 arguments are specified for a function that accepts 2 arguments in the following code.
def add_two_value(x, y):
total = x + y
return total
add_two_value(100, 200, 300)
TypeError: add_two_value() takes 2 positional arguments but 3 were given
When I read the error message, it says something like "The add_two_value function takes two arguments, but three arguments are specified." In this way, the number of arguments that a function can accept is basically limited.
On the other hand, if you accept any number of arguments, you can implement flexible behavior with one function, such as "calculate with the value of 3 arguments" or "calculate with the value of 5 arguments". ..
To create such a function, use a half-width asterisk in the argument part of the function in the same way as when executing the function. As for the argument name, the name ʻargsis often used as the "argument group of arbitrary functions" by convention. Often used in the form
* args` with an asterisk.
The * args
argument is set as a tuple (it looks like the list that doesn't change values, as mentioned in the previous chapter).
def print_args(*args):
print(args)
The contents of the function just print out the contents of the passed * args
arguments.
Let's try it with 3 arguments.
print_args(100, 200, 300)
Output contents of code execution result:
(100, 200, 300)
If you look at the output of * args
, you can see that the one that stores the three values is output properly. Also, you can see that even though the function has only * args
as an argument, no error occurs even if three arguments are specified.
Now let's execute the function with 5 arguments.
print_args(100, 200, 300, 400, 500)
Output contents of code execution result:
(100, 200, 300, 400, 500)
You can see that the contents of the specified and 5 arguments are output in the function without any error.
The ʻargs argument set by the description such as
* args can also refer to the value by index like a list. For example, if you want to refer to the first value (index of 0), you can access the first value of the argument by writing ʻargs [0]
.
In the code below, the first argument is printed in the function, and as a result, the first 100 is displayed (print (args [0])
).
def print_args(*args):
print(args[0])
print_args(100, 200, 300)
Output contents of code execution result:
100
Earlier, I created a function that accepts any number of arguments. This time, I will explain the function that accepts keyword arguments with arbitrary argument names.
As with normal arguments, if you specify an argument that is not set in the function as it is with a keyword argument, an error will occur as shown in the code below (a keyword argument x that does not exist in the function argument is specified).
def multiply_two():
return x * 2
multiply_two(x=100)
TypeError: multiply_two() got an unexpected keyword argument 'x'
When I read the error message, it says something like "The multiply_two function received an unexpected keyword argument of x". This error message occurs because the argument x is specified even though the argument x is not defined.
To set the function to accept arbitrary keyword arguments, set two single-byte asterisks in a row immediately before the argument name in the function argument. The argument name kwargs
is often used for this argument. The argument name is a shortened version of the English ** k ** ey ** w ** or ** ar ** guidance ** s ** keyword argument. It is written as ** kwargs
with two asterisks.
Write the code and give it a try.
def print_kwargs(**kwargs):
print(kwargs)
print_kwargs(x=100, y=200)
Output contents of code execution result:
{'x': 100, 'y': 200}
Each specified keyword argument is stored in kwargs
. kwargs
is a dictionary, and argument names (x and y in this sample) are set in the key, and each value (100 and 200 in this sample) is stored.
[1]. Let's create a function that takes one integer argument, doubles the value of that argument, and returns it. Also, let's execute the function and output the received return value with print. The argument name can be anything.
[2]. The following code resulted in an error. Let's fix it so that it does not cause an error.
def print_value(value):
print(value)
File "<ipython-input-21-def08fe6f21b>", line 2
print(value)
^
IndentationError: expected an indented block
[1]. To create a function, write def function name ():
. Also, since the question says "receive one integer argument", the argument x is set in the example answer (a different name is acceptable).
def multiply_two(x):
x *= 2
return x
multiplied_x = multiply_two(100)
print(multiplied_x)
Output contents of code execution result:
200
Also, to set the return value, write return return value
in the function. In the above code, the return x
part is applicable.
[2]. One indent is required in the function. Set the indent with four half-width spaces. Even if the number of spaces is other than 4 (2 etc.), no error will occur, but since the Python coding standard stipulates 4 spaces, set 4 spaces unless there is a special reason. I will.
If you use the code with indentation before the print (value)
part as shown below, no error will occur.
def print_value(value):
print(value)
[1]. When I created and executed a function for processing that adds 1 to a variable called dog_age
as shown below, an error occurred. Let's edit the code so that there are no errors.
dog_age = 10
def increment_dog_age():
dog_age += 1
increment_dog_age()
UnboundLocalError Traceback (most recent call last)
<ipython-input-23-37cd012f49bf> in <module>
6
7
----> 8 increment_dog_age()
<ipython-input-23-37cd012f49bf> in increment_dog_age()
3
4 def increment_dog_age():
----> 5 dog_age += 1
6
7
UnboundLocalError: local variable 'dog_age' referenced before assignment
[2]. Let's create a function that accepts three arguments x, y, and z and returns the sum of each argument. Also, try executing that function and print out the result.
[1]. The variable dog_age
is an integer. Integer global variables cannot be referenced directly within a function. To refer to an integer global variable in a function, you need to specify global
and the variable, or treat it as a local variable using arguments and return values.
In the case of specifying global
in the function, write as follows. You can see that it runs without error and the resulting value of dog_age
is incremented by 1 to 11.
dog_age = 10
def increment_dog_age():
global dog_age
dog_age += 1
increment_dog_age()
print(dog_age)
Output contents of code execution result:
11
Or you can write as follows using arguments and return values. Whichever you use, you will get the same result, but it is preferable to reduce the number of global variables used in the function if possible, so basically this is recommended.
dog_age = 10
def increment_dog_age(dog_age):
dog_age += 1
return dog_age
dog_age = increment_dog_age(dog_age)
print(dog_age)
Output contents of code execution result:
11
[2]. If you want to set multiple arguments, set a half-width comma between each argument. Insert one half-width space after the comma.
def calculate_total(x, y, z):
return x + y + z
total = calculate_total(100, 200, 300)
print(total)
Output contents of code execution result:
600
[1]. Executing the following code will result in an error. Let's adjust so that no error occurs.
def calculate_x_plus_y(x, y):
total = x + y
return total
calculate_x_plus_y(100)
4
5
----> 6 calculate_x_plus_y(100)
TypeError: calculate_x_plus_y() missing 1 required positional argument: 'y'
[2]. Let's create a function with an argument named x that can be omitted and has an argument that sets a value of 100 if the specification is omitted. It doesn't matter what the function does.
[3]. Execute the function by specifying only the argument of y in the following function.
def calculate_total(x=100, y=200, z=300):
total = x + y + z
return total
[1]. While the function requires two arguments, x and y, only one argument is specified where the function is executed. If you set two arguments at the execution location of the function, the error will disappear.
def calculate_x_plus_y(x, y):
total = x + y
return total
total = calculate_x_plus_y(100, 200)
print(total)
Output contents of code execution result:
300
[2]. To specify an optional argument, set the default value for the argument. To set the default value, set a half-width equal symbol between them in the form of argument = default value
. Write without spaces before and after the equal. In this problem, write as x = 100
.
def print_x(x=100):
print(x)
print_x()
Output contents of code execution result:
100
[3]. If you want to specify only the middle y of the three arguments, use the keyword argument. To use keyword arguments, specify them in the form argument name = value
when executing the function. In this problem, specify in the format of y = 500
.
total = calculate_total(y=500)
print(total)
Output contents of code execution result:
900
[1]. Try executing the function by specifying the variable in the list of ʻarg_value_listin the following code as the ** list ** in the argument of the
calculate_total` function.
arg_value_list = [100, 200, 300]
def calculate_total(x, y, z):
total = x + y + z
return total
calculate_total(
arg_value_list[0],
arg_value_list[1],
arg_value_list[2],
)
[2]. Try to create a function that accepts any number of arguments (3 or 5). It doesn't matter what the function does.
[1]. To assign each value in the list to an argument, specify a half-width asterisk immediately before the list. In this problem, we will write * arg_value_list
.
total = calculate_total(*arg_value_list)
print(total)
Output contents of code execution result:
600
[2]. To create a function that accepts any number of arguments, set a half-width asterisk before the argument name, such as * args
, in the argument setting part of the function.
def print_args(*args):
print(args)
print_args(100, 200, 300)
Output contents of code execution result:
(100, 200, 300)
――A function is a set of programs that can be executed from various locations and can implement various behaviors using arguments and return values.
--By using functions, you can reduce code duplication and write code with high maintainability.
--Use the keyword def
to create a function.
--Indentation of 4 half-width spaces is required in the function. If you do not indent, an error will occur.
--To execute a function, write something like function ()
(eg calculate_total ()
).
--Global variables such as numbers and strings cannot be referenced directly in the function. You need to use global
to specify that the variable in question is a global variable.
--Dictionaries and lists can be referenced in functions without specifying global
.
--Various parameters can be passed to the function by setting the argument to the function.
--Use the default value if you want to set an optional argument.
--By using the keyword argument, you can specify the argument value by specifying both the argument name and the value. This is convenient when there are many arguments.
--If you specify a numerical value or character string as an argument, the value is copied and treated as a local variable in the function (passed by value).
--If a list or dictionary is specified as an argument, the value will not be copied (pass by reference).
--By using a half-width asterisk for the argument part, you can expand a list or dictionary as an argument, or create a function that accepts any number of arguments or keyword arguments with arbitrary argument names.
Besides, I write various articles mainly on Python. Please do that too! Main articles posted so far
-Python / Functions -Scope --Wikipedia -Magical number <~ 3 to 5 pieces of information that people can remember! ?? ~> -Why the argument is called Argument -I can't say it's passed by reference anymore -[Effective Python-59 items to improve Python programs](https://www.amazon.co.jp/Effective-Python-%E2%80%95Python%E3%83%97%E3%83%AD%E3 % 82% B0% E3% 83% A9% E3% 83% A0% E3% 82% 92% E6% 94% B9% E8% 89% AF% E3% 81% 99% E3% 82% 8B59% E9% A0 % 85% E7% 9B% AE-Brett-Slatkin / dp / 4873117569 /)
Recommended Posts