There is no madness to my methods functions
Being functional
- Up to this point when we were confronted with a problem, our contribution was a single program file.
- In the future our contribution will often involve multiple files.
- One file will still be the program.
- The other file(s) will be modules that define functions in support of the program task. We already have lots of functional experience with built-in functions and standard module functions.
- While module is the Python term for a file of related functions definitions, programmers also use the terms library, API (application programmer interface), and programming toolbox.
- In programming documentation, it is common practice to include a pair of parentheses when referencing a function. The parentheses clue the reader that a function is being discussed.
Why have functions
- Complex problem solving requires that we break a problem down into tasks that when put together, solve the problem. If the component tasks are also complex, the breaking down process can be repeated to determine the sub-tasks needed for solving the major tasks.
- This form of problem solving is called top-down design; there is also bottom-up design and object-oriented design. Object-oriented design is the focus of the second course in digital problem solving at UVA.
- In digital problem solving, the component tasks are written as independent units of code. For clarity, code units are named so that there is no ambiguity as to what unit is being considered. In Python we call a named unit of code, a function.
- We use functions to provide an easier, clearer, and often reusable way for the manipulation and calculation of values. In designing a function we need to determine
- What information is needed upon startup;
- What information it is to produce; and
- Provide an algorithm for going from one to the other.
Function definition syntax and terminology
- A typical Python function definition looks like the following
def function-name
(
parameters)
:
'''
header-comment'''
action
The keyword
def
signals that a function is being defined.
The function-name is an identifier that names the task.
The
(
parameters)
are a list of variable names (identifiers). The values of the parameters are the values needed by the function upon start up. The function-name along with the parameters form the function header.
The colon (
:
) is a separator of the function header from the function statement block.
Although optional, the literal string
'''
header-comment'''
is normally the first line following the function header. The header-comment is referred to in Pythonics as a doc string and describes the operation of the function.
The action is the block of statements to be executed when the function is called upon. The statements can include a
return
statement(s) that specifies the value to be associated with the function's usage. Note,return
is a keyword.
Function invocation syntax and terminology
- The starting up of a function is called an invocation. A non-built-in function invocation has form
module-name . function-name ( arguments )
- The module-name is the name of the
.py
file containing the definition of function function-name(). Like function-name, a module-name must be an identifier.
- Operator . is the selection operator. It indicates that a component of the indicated module is to be accessed.
- The function-name is the name of the function being invoked.
- The ( arguments ) are a list of values that are passed to the function so that it can carry out its task.
- The following code snippet from wc.py gets the contents of a user-specified web site by invoking function
url.get_contents()
. In programming documentation, it is common practice to include a pair of parentheses when referencing a function. The parentheses clue the reader that a function is being discussed.
import url
reply = input( 'Enter web file: ' )
link = reply.strip()
text = url.get_contents( link )
- Observe that the program begins with an
import
statement. Just as standard Python modules must be imported for program usage, so too must local modules.
- Preferences can be set where Python looks for local modules. By default, Python always searches for a module in the same folder as the program making the invocation.
- The ability to reuse functions within a program and across programs is a major part of what make modules so attractive.
Function invocation semantics — what happens under the hood
- When Python encounters a function invocation, it performs preparatory work before starting up the invoked function.
- Python first checks that the number of invocation arguments, matches the number of parameters specificed in the function definition. If the counts match, the arguments are evaluated; that is, their values are determined.
- Python then sets aside some computer memory for carrying out the function. In progamming speak (parlance), that memory is called an activation record.
- The activation record stores values of the parameter variables. The parameter variables are initialized with the argument values. If a function needs other variables to perform its task, those variables are also stored there.
- Once the parameters of an invoked fuction are initialized, the flow of control is given to the function — its actions are carried out. After the function completes, the flow of control is handed back to the invoking code where it picks up the running of its code at the point of the invocation.
- If a
return
statement is encountered during the execution of a function, the value of the expression (if any) following keywordreturn
is determined. The value of the return expression is the value of the function invocation. That is, when a function invocation is encountered during program execution, the invocation is evaluated. The evaluation value is the value from the return statement.
- All invoked Python functions return a value. If there is no explicit return value supplied, a Python function invocation returns
None
. As you should recall, keywordNone
indicates no value is available.
- The following code snippet
s = "Cole's law: marinate shredded cabbage in vinaigrette."
x = print( s )
print( x )
indicates even the
print()
function returns a return. The snippet output is
Cole's law: marinate shredded cabbage in vinaigrette.
None
Staying within the law of scope
- Parameters and other function variables are collectively called local variables. Local variables only exist during that invocation.
- When a function completes, its activation record memory is released back to the system. That means referencing a local variable is not possible outside the function with the flow of control. We say that the scope of the local variables is limited to the function.
- As an example, consider program test_locality.py that tries to access the local variable
bytes
from the definition ofurl
module functionget_contents()
.
import url
page = url.get_contents( 'http://www.cs.virginia.edu/~cs1112/' )
print( url.get_contents.bytes )
- The program terminates with a traceback indicating there is no
bytes
to reference. The restriction on local variable usage is symmetric — the invoking function cannot reference the local variables of the function doing the invocation.
For the enquiring mind (and you are all enquiring)
- Look at Hands on Python
- Two www.python.org resources should be examined now and also re-examined later.
- The Python Tutorial includes a section on functions. I recommend before going there to thoroughly review the discussion presented here.
- Python enhancement proposal 008 (PEP 008) includes recommended practices for naming modules, functions, and variables. The recommendations suggest that function and variable names are as a rule written in snake_case; that is, lower-case words joined by underscores. Module names are expected to be short, lower-case, and no separation between words. I will add that function names are often action or verb phrases; e.g.,
input_integer()
.
- Coding bat for practice writing functions