(Python) Subroutines: Procedures and Functions - 1


Subroutines

A subroutine is a separate part of the program that has a name and solves its own separate task. The subroutine is located at the beginning of the main program and can be launched (called) from the main program by specifying the name.

Using subroutines allows you to avoid code duplication, if you need to write the same code in different places in the program. 
Libraries that are imported into a program (for example, the math library math) consist of subroutines that have already been compiled by someone. Programmers do not need to think about what algorithms they implement, but simply apply them, thinking only about what exactly they are doing. This is a big time saver. There is no need to write an algorithm that has already been written by someone else.

Each subroutine should only do one task,  either just calculate something, or output some data, or do something else. 

There are two types of subroutines - proceduresand functions.

Sub-procedures perform some action, such as displaying a result on the screen in a certain form (a simple example, the print() statement is a standard sub-procedure that prints data to the screen).

Function subroutines return a result (number, character string, etc.) that we can use in the main program.

Let's try to write a simple procedure:
Suppose we need to display the string "Error" on the screen every time an error can occur in the code due to the fault of the user. For example, when he enters incorrect data.
This can be done by writing the operator print("Error") And now imagine that such a line needs to be inserted in many places in the program. Of course, you can just write it everywhere. But this solution has two drawbacks.
1) This string will be stored in memory many times.
2) If we want to change the output on error, we will have to change this line throughout the program, which is rather inconvenient

For such cases, procedures are needed.
A program with a procedure might look like this:
  def printError(): # procedure description print("Error") ... printError() # start the procedure for execution. # Just specify the name of the procedure we want to execute ... printError()
Need to remember!
  1. The procedure begins with the word def (from English - define - to define). After the name of the procedure, empty brackets and a colon are written. Parameters can be specified inside the brackets (we will talk about this later).
  2. All statements that are executed in a procedure are indented. 
  3. To execute a procedure, in the main program you need to call it by name and remember to write parentheses!
  4. You can call a procedure in a program as many times as you like.

Parameters and Arguments

Now let's imagine that we need to display different messages in response to a user's error, depending on what kind of mistake he made.
In this case, you can write your own procedure for each error:  
def printErrorZero():
    print("Error. Division by zero!")
def printErrorInput():
    print("Error in input!")

What if there are many more possible errors? This solution will not suit us!
We need to learn how to control the procedure by telling it what error message to display.
To do this, we need parameters that we will write in parentheses after the procedure name
def printError(s):
    print("s")

In this procedure, s is a parameter - a special variable that allows you to control the procedure.
 
The parameter is a variable that determines how the subroutine works. Parameter names are comma-separated in the subroutine header.


Now, when calling the procedure, you need to indicate in brackets the actual value that will be assigned to the parameter (variable s) inside our procedure
printError("Error! Division by zero!")

Such a value is called an argument.
 
The argument is the parameter value that is passed to the subroutine when it is called.

An argument can be not only a constant value, but also a variable or an arithmetic expression.

Local and global variables

Variables that are introduced in the main program are called global (or shared).

You can access global variables from any subroutine. 

It is often necessary to introduce additional variables that will only be used in the subroutine. Such variables are called local (or local). You can work with them only inside the subroutine in which they are created. The rest of the routines don't "know" anything about them.

Thus, it is possible to limit the scope (scope) of a variable only to the subroutine where it is really needed. In programming, this technique is called encapsulation  - hiding the variable from being changed from outside.

Analyze three programs:
Description Program
1) In this program, the variable i is local. If there is no i variable in the main program, then we will get an error message. And if there is such a variable (then it is a global variable), then its value is displayed on the screen.
def test():
    print(i)
2) Here, even if there is a global variable i, a new local variable i will be created with a value of 2, and 2 will appear on the screen.
def test():
  i = 2
    print(i)
3) In this program, there is a global variable i with a value of 15. Its value can be changed inside the subroutine, for this it is necessary to explicitly declare that it is global (use the command global ).
The procedure will work with the global variable i and it will be assigned a new value of 2. The value 2 is displayed.
def test():
  global i
    i = 2
    
# main program
i = 15
print(i)