Coding for Beginners in Easy Steps: Basic Programming for All Ages (2015)
6. Creating functions
This chapter demonstrates how to code re-usable blocks of code in your programs.
Defining blocks
Adding parameters
Returning results
Storing functions
Importing functions
Summary
Defining blocks
Previous examples in this book have used built-in functions of the Python programming language, such as the print() function. However, most programs have a number of coder-defined custom functions that can be called as required when the program runs.
A custom Python function is created using the def (definition) keyword followed by a name of your choice and ( ) parentheses. The coder can choose any name for a function except the keywords of the programming language and the name of an existing built-in function. This line must end with a : colon character, then the statements to be executed whenever the function gets called must appear on lines below and indented. Syntax of a function definition, therefore, looks like this:
def function-name ( ) :
statements-to-be-executed
statements-to-be-executed
Function statements must be indented from the definition line by the same amount so the Python interpreter can recognize the block.
Once the function statements have been executed, program flow resumes at the point directly following the function call. This modularity is very useful in programming to isolate set routines so they can be called upon repeatedly.
To create custom functions it is necessary to understand the accessibility (“scope”) of variables in a program:
•Variables created outside functions can be referenced by statements inside functions – they have “global” scope
•Variables created inside functions cannot be referenced from outside the function in which they have been created – these have “local” scope
The limited accessibility of local variables means that variables of the same name can appear in different functions without conflict.
Avoid using global variables in order to prevent accidental conflict – use only local variables where possible.
If you want to coerce a local variable to make it accessible elsewhere it must first be declared with the Python global keyword followed by its name only. It may subsequently be assigned a value that can be referenced from anywhere in the program. Where a global variable and a local variable have the same name, the function will use the local version.
def.py
Start a new program by initalizing a global variable
global_var = 1
Next, create a function named “my_vars” to display the value contained within the global variable
def my_vars() :
print( ‘Global variable:’ , global_var )
Now, add indented statements to the function block to initialize a local variable and display the value it contains
local_var = 2
print( ‘Local variable:’ , local_var )
Then, add indented statements to the function block to create a coerced global variable and assign an initial value
global inner_var
inner_var = 3
Add a statement after the function to call upon that function to execute the statements it contains
my_vars()
Finally, add a statement to display the value contained in the coerced global variable
print( ‘Coerced Global:’ , inner_var )
Save then run the program – to see the custom function display the variable values
Variables that are not global but appear in some outer scope can be addressed using the nonlocal keyword.
Adding parameters
When defining a custom function in a program you may optionally specify a “parameter” name between the function’s parentheses. An “argument” value can then be passed to that parameter by specifying the value in the parentheses of the call to the function. The function can now use that passed in value during its execution by referencing it via the parameter name. For example, defining a function to accept a parameter to print out:
def echo( user ) :
print( ‘User:’ , user )
Parameters are special variables for internal use only within a function – they must adhere to the same naming rules as regular variables.
A call to this function must specify an argument value to be passed to the parameter in its parentheses so it can be printed out:
echo( ‘Mike’ )
Multiple parameters can be specified in the function definition by including a comma-separated list of parameter names within the function parentheses:
def echo( user , lang , sys ) :
print( User:’ , user , ‘Language:’ , lang , ‘Platform:’ , sys )
When calling a function whose definition specifies parameters, the call must include the same number of arguments as parameters. For example, to call this example with multiple parameters:
echo( ‘Mike’ , ‘Python’ , ‘Windows’ )
The passed values must appear in the same order as the parameter list unless the caller also specifies the parameter names like this:
echo( lang = ‘Python’ , user = ‘Mike’ , sys = ‘Windows’ )
Optionally, a default value may be specified in the parameter list when defining a function. This will be overridden when the caller specifies a value for that parameter but will be used by the function when no argument value gets passed by the caller:
def echo( user , lang , sys = ‘Linux’ ) :
print( User:’ , user , ‘Language:’ , lang , ‘Platform:’ , sys )
This means you may call the function passing fewer values than the number of parameters specified in the function definition, to use the default parameter value, or pass the same number of values as specified parameters to override the default value.
Name parameters the same as variables passed to them to make the data movement obvious.
param.py
Start a new program by defining a function with three parameters that will print out passed-in argument values
def echo( user , lang , sys ) :
print( ‘User:’, user, ‘Language:’, lang, ‘Platform:’, sys )
Next, call the function passing string argument values to the function parameters in the order they appear
echo( ‘Mike’ , ‘Python’ , ‘Windows’ )
Now, call the function passing string arguments to the function parameters by specifying the parameter names
echo( lang = ‘Python’ , sys = ‘Mac OS’ , user = ‘Anne’ )
Then, define another function with two parameters having default values that will print out parameter values
def mirror( user = ‘Carole’ , lang = ‘Python’ ) :
print( ‘\nUser:’ , user , ‘Language:’ , lang )
Finally, add statements to call the second function both using and overriding default values
mirror()
mirror( lang = ‘Java’ )
mirror( user = ‘Tony’ )
mirror( ‘Susan’ , ‘C++’ )
Save then run the program – to see the function display the argument values or default parameter values
Arguments are the actual data values passed to function parameters by the function call.
Returning results
Like Python’s built-in str() function, which returns a string representation of the value specified as its argument by the caller, your custom functions can also return a value to their caller by using the return keyword to specify a value to be returned. For example, to return to the caller the total of adding two specified parameter values like this:
def sum( a , b ) :
return a + b
The returned result may be assigned to a variable by the caller for subsequent use by the program like this:
total = sum( 8 , 4 )
print( ‘Eight Plus Four Is:’ , total )
Or the returned result may be used directly “in-line” like this:
print( ‘Eight Plus Four Is:’ , sum( 8 , 4 ) )
Typically, a return statement will appear at the very end of a function block to return the final result of executing all statements contained in that function.
A return statement may, however, appear earlier in the function block to halt execution of all subsequent statements in that block. This immediately resumes execution of the program at the caller. Optionally, the return statement may specify a value to be returned to the caller or the value may be omitted. Where no value is specified, a default value of None is assumed. Typically, this is used to halt execution of the function statements after a conditional test is found to be False. For example, where a passed argument value is below a specified number:
def sum( a , b ) :
if a < 5 :
return
return a + b
You can specify a default value for a parameter in the function definition.
In this case, the function will return the default value None when the first passed argument value is below five and the final statement will not be executed.
Where the function is to perform arithmetic, user input can be validated for integer values with the built-in isdigit() function.
return.py
Start a new program by initializing a variable with user input of an integer value for manipulation
num = input( ‘Enter An Integer:’ )
Next, add a function definition that accepts a single argument value to be passed from the caller
def square( num ) :
Now, insert into the function block an indented statement to validate the passed argument value as an integer or halt further execution of the function’s statements
if not num.isdigit() :
return ‘Invalid Entry’
Then, add indented statements to cast the passed argument value as an int data type then return the sum of squaring that value to the caller
num = int( num )
return num * num
Finally, add a statement to output a string and the returned value from the function call
print( num , ‘Squared Is:’ , square( num ) )
Save then run the program – to see the function display the returned values
Remember that user input is read as a str data type – so must be cast into an int or float data type for arithmetic.
Storing functions
Function definitions can usefully be stored in one or more separate files for easier maintenance and to allow them to be used in several programs without copying the definitions into each one. Each Python file storing function definitions is called a “module” and the module name is the file name without the “.py” extension.
Functions stored in the module are made available to a program using the Python import keyword followed by the module name. Although not essential, it is customary to put any import statements at the beginning of the program.
Imported functions can be called using their name dot suffixed after the module name. For example, a “steps” function from an imported module named “ineasy” can be called with ineasy.steps().
Where functions stored in a module include parameters, it is often useful to assign a default value to the parameter in the definition. This makes the function more versatile as it becomes optional for the call to specify a parameter value.
cat.py
Start a new module by defining a function that supplies a default string value to its parameter for display
def purr( pet = ‘A Cat’ ) :
print( pet , ‘Says MEOW!’ )
Next, add two more function definitions that also supply default string values to their parameters for display
def lick( pet = ‘A Cat’ ) :
print( pet , ‘Drinks Milk’ )
def nap( pet = ‘A Cat’ ) :
print( pet , ‘Sleeps By The Fire’ )
Now, save the file as “cat.py” so the module is named “cat”
Start a new program with a statement to make the “cat” module functions available
import cat
kitty.py
Next, call each function without supplying an argument
cat.purr()
cat.lick()
cat.nap()
Now, call each function again and pass an argument to each then save the file
cat.purr( ‘Kitty’ )
cat.lick( ‘Kitty’ )
cat.nap( ‘Kitty’ )
Start another program by making the “cat” module functions available once more
import cat
Then request the user enters a name to overwrite the default parameter value
pet = input( ‘Enter A Pet Name: ‘ )
Finally, call each function passing the user-defined value as the argument
cat.purr( pet )
cat.lick( pet )
cat.nap( pet )
Save then run these programs – to see output from the imported module in each program
tiger.py
You can create an alias when importing a module using import as keywords. For example, import cat as tom allows you to use tom as the function prefix in calls.
Importing functions
Internally, each Python module and program has its own “symbol table” which is used by all functions defined in that context only. This avoids possible conflicts with functions of the same name in another module if both modules were imported into one program.
When you import a module with an import statement, that module’s symbol table does not get added to the program’s symbol table – only the module’s name gets added. That is why you need to call the module’s functions using their module name prefix. Importing a “steps” function from a module named “ineasy” and another “steps” function from a module named “dance” means they can be called without conflict as ineasy.steps() and dance.steps().
Where you import individual function names, the module name does not get imported – so it cannot be used as a prefix.
Generally, it is preferable to avoid conflicts by importing the module name and calling its functions with the module name prefix, but you can import individual function names instead with a from import statement. The module name is specified after the from keyword, and functions to import are specified as a comma-separated list after the import keyword. Alternatively, the * wildcard character can be specified after import to import all function names into the program’s own symbol table. This means the functions can be called without a module name prefix.
dog.py
Start a new module by defining a function that supplies a default string value to its parameter
def bark( pet = ‘A Dog’ ) :
print( pet , ‘Says WOOF!’ )
Next, add two more function definitions that also supply default string values to their parameters
def lick( pet = ‘A Dog’ ) :
print( pet , ‘Drinks water’ )
def nap( pet = ‘A Dog’ ) :
print( pet , ‘ Sleeps In The Sun’ )
Save the file as “dog.py” so the module is named “dog”
pooch.py
Start a new program with a statement to make individual “dog” module functions available
from dog import bark , lick , nap
Next, call each function without supplying an argument
bark()
lick()
nap()
Now, call each function again and pass an argument value to each then save the file
bark( ‘Pooch’ )
lick( ‘Pooch’ )
nap( ‘Pooch’ )
Start another program by making all “dog” module functions available
from dog import *
Request a user entry to overwrite the default parameter
pet = input( ‘Enter A Pet Name: ‘ )
Finally, call each function passing the user-defined value as the argument
bark( pet )
lick( pet )
nap( pet )
Save then run these programs – to see output from the imported functions
fido.py
For larger programs you can import modules into other modules to build a module hierarchy.
Summary
•Functions are defined using the def keyword followed by a name of your choice and () parentheses
•A function definition line must end with a : colon character and its block of statements to execute when the function gets called must be indented below that line
•Variables with global scope can be referenced from anywhere within that program
•Variables with local scope can only be referenced from within the function in which they are declared
•A local variable can be coerced to make it globally accessible by first declaring it using the global keyword
•Function parameters are special variables for use only within a function, and arguments are data values passed to parameters
•Parameters are declared as a comma-separated list within the parentheses of a function definition
•Function calls must supply argument data for each function parameter unless a default value is specified in their declaration
•Data passed to parameters in a function call must appear in the same order as the parameters unless their names are specified
•Optionally, the return keyword can be used within a function to return a value to the caller
•Functions can be stored in modules that are named as the file name without the “.py” file extension
•An import statement makes module functions available in a program by dot-suffixing their name after the module name
•Internally, each Python module has its own symbol table so like-named functions in different modules do not conflict
•A from import statement makes module functions available in a program without the need to dot-suffix their name
•An import * statement can be used to import a module’s functions into the program’s own symbol table