“It is usual in mathematics—outside of mathematical logic—to use the word function imprecisely and to apply it to forms such as y2 + x. Because we shall later compute with expressions for functions, we need a distinction between functions and forms and a notation for expressing this distinction. This distinction and a notation for describing it, from which we deviate trivially is given by Church.”
John McCarthy et al.
The function is the simplest construct able to describe a behavior. Functions can behave similarly as in math: they compute a number from a given number or numbers. Functions in programming languages are of a somewhat more general construction, though: they generate a new object by executing statements from given objects. In this chapter, you will learn how functions work in programming languages and about related concepts such as blocks.
Calling a Function
Calculation of an Absolute Value
Calculation of a Rounded Value
The built-in types of the Python language cannot always accurately store decimals. This is a consequence of the binary representation of decimals in memory. For example, the 3848.9 value shown in the previous example is stored as 3848.90000000000009. How to store best financial data in Python is described in detail in Chapter 6.
Calculation of a More Complicated Expression
Side Effects of Functions
The function concept in the programming languages is more general than that in the mathematical sense, as previously clarified. An important difference is that functions can have side effects. By side effects, we mean it not only calculates a value and that value will be returned, but it also changes something in its environment: changes the value of an object in the environment of a function, displays text to the screen, saves a file, sends an email on the network, etc.
The Python language even allows a function to not have a result object. In this case, its return value will be a None object . This makes sense, usually, when the function completes its task by causing a side effect (e.g., writing a string to display, writing to a file, etc.).
Function with a Side Effect
Function with Multiple Parameters
Input and Output Statements
Function Arguments
Arguments have so far been specified to functions by listing them in due order. This method of argument specification is referred to as positional parameter specification. However, it is possible to specify an argument not only according to position but also as a keyword argument.
There are two important arguments of the print() function that can be specified as keyword arguments: the sep and end arguments. These arguments can be strings: the first one specifies which separator character should be printed between the printed values, and the second one specifies what is printed at the end of the line. Among the arguments of the function, the positional arguments should always precede the keyword parameters.
Specification of Keyword Arguments
The other feature you can observe is that the print() function has any number of positional parameters. We speak of a variable-length parameter list, and at the function call you specify them as normal fixed parameters. This is useful in cases when it is not known in advance how many arguments will be specified.
Defining a Function
Now that you have seen how to call functions, you will learn how to define your own function. Defining a function always begins with the def keyword, followed by the name of the function, and the parentheses optionally with parameters; then the statements constituting the function come on new lines after a colon. Parameters are listed in parentheses separated by commas, and the values of these variables will be defined by the arguments during the call of the function.
Function parameter or argument? When the variable names are listed in the function definition to be required at the function call, they are called parameters or formal arguments. When values are specified in the function call to be passed, they are called arguments or actual arguments. In practice, parameter and argument are often used imprecisely in an interchangeable way, and their exact meaning can be figured out from the context.
Function Definition
Call of the Defined Function
Blocks
The space and the tab are two different characters. How many spaces are included in a tab depends on the settings. This is the reason mixed space and tab characters are not allowed to be used to indent blocks. The official recommendation is to use four spaces for every block. Compliance to this is assisted by development tools supporting the Python language: they replace tabs automatically with spaces.
A block corresponding to a function definition is called a function body . Statements forming the function can contain a return keyword and an expression after it. This statement indicates the end of the function and value of the expression will be the result of the function . When no such statement is present, the function has no results; i.e., its result is None as discussed earlier.
Keyword Arguments
Call of the Defined Function with Keyword Arguments
Function Definition with Default Parameters
Calling the Defined Function with Various Arguments
Visibility of Names
A name defined outside but before the function definition (in the block containing the definition of the function or any of the blocks containing the particular block) is visible from the function (only to access the object referenced by the name).
Function Referencing to an Outer Variable Name
A name is assigned to an object in the function body (inside the block belongs to the function), and a reference can be made to the name only inside the function after the assignment; the name is not visible outside the function. If the name is identical to a name defined outside the function, this new assignment will be in effect, but it does not change the assignment outside the function. In other words, by leaving the function, the object assigned to the name outside the function will be reachable with the name (it will not be overwritten; it only will be shadowed within the function). In Listing 2-15, the result of the total_sum_v4 function call will be 30000.
Function Referencing a Shadowed Outer Variable Name
The previous two use cases cannot be mixed. That is, if a value that was also defined outside the function is assigned at any point in the function body, the reference preceding the definition in the function body will refer to the name inside the function body (an error message is given in this case indicating that no object assignments took place to the name yet, instead of accessing the value outside the function).
Functions as Parameters
Function as Argument
Definitions of Nested Functions
Nested Function Definition
Functions in Practice
Three types of notations can help you when defining functions: define the parameter and return types, specify the preconditions with respect to the parameters, and include a detailed documentation string. These three notations are completely optional and primarily do not affect the behavior of a function.
Similar to the way type hints were defined for variable names in Chapter 1, the types of function parameters can be written after the name, separated by a colon. The return type of the function can be written after the function parameters, separated from it by an arrow (->).
Function can begin with a so-called documentation string (docstring) , which provides a description of the function, that can be queried. The documentation string is a multiline comment that contains the task of the function briefly, on one line; its detailed description separated by one empty line; and finally, a description of the parameters after the Args: word.
After the documentation string, the preconditions can be represented to describe the conditions necessary for the function to work properly. These can be described with the assert statement : an assert keyword followed by a Boolean expression and optionally by an error message separated by a comma. If the preconditions expressed by the Boolean expression is not fulfilled, an error is given.
By convention, there is no space between the function name and the parentheses when calling the functions, as you saw in the examples. As to the commas, it is recommended to put a space only after the comma.
Function Definition
Discount Calculator
Advanced Details
This section describes some technical details in reference manual style and advanced concepts that may need more technical background.
Namespace and Scope
A namespace is an object that stores the mapping of names (variable names, function names, etc.) to objects. The outermost user-accessible namespace of the program is called the global namespace. In addition, there are so-called built-in namespaces that include the names of the built-in objects. The definition of the function creates a new namespace called a local namespace . Functions can contain further function definitions; thus, an arbitrary number of nested local namespaces can be constructed. This way, namespaces form a tree-like hierarchy, the root of which is the built-in namespace.
The scope of a variable name is part of the source code where a name of a namespace can refer. Resolution of a referenced name takes place by finding the assignment in the relevant local or global namespace. If this is unsuccessful, an attempt is made to find it in the next namespace outside the referenced one. The last namespace in the hierarchy is the built-in namespace. If it cannot be resolved even in this namespace, an error will be raised. Namespaces can “shadow name” each other in case an identical name is defined. This shadowing behavior can be changed by two statements: a local namespace outside of the local and global namespaces can be referenced by a nonlocal statement and a global statement (which consist of the keyword and the variable name), respectively.
Positional-Only and Keyword-Only Parameters
Function with Positional-Only and Keyword-Only Parameters
Variable Number of Arguments
You saw in the examples of the function call in Listings 2-4 and 2-5 that functions can have a variable number of arguments . The notation that can be used for this is a star put in front of the parameter’s name. This parameter will then be a special parameter that does not behave like a simple positional parameter, but an object that will contain all the positional arguments that were not assigned to the preceding parameters. If there are two stars, the parameter will contain the keyword arguments that were not assigned to the preceding parameters.
Variable Number of Arguments
Lambda Expression
Simple Function as Parameter
Lambda Expression as Parameter
Decorator
A decorator is a special notation to modify the behavior of the function. The decorator is in fact a function receiving a function as a parameter and returning a function as a result. It can be used in two typical ways: it records the obtained function into some global data structure and returns with the function originally received, or it returns with another function instead of that received as a parameter. Depending on the purpose of this new function, it can carry out operations before and after calling the original function.
Decorators
Yield Statement and Asynchronous Functions
Functions that contain yield statements behave differently than the functions discussed in this chapter. They are called generator functions or co-routines, and you can find more information on them at the end of Chapter 4. These kinds of functions are the core building blocks of so-called asynchronous functions. We discuss them separately in Appendix C.
Key Takeaways
A function call is an expression that can be denoted by writing parentheses (this is called a function call operator) after the name of the function. The parentheses can contain further expressions that are the arguments of the function. Calling a function means executing the statements assigned to the function. The function usually describes some calculations or changes its environment. The function call usually returns a value that can be used.
Defining a function requires nothing more than assigning a block (list of statements) to a name. In the definition of a function, the parameters expected by the function can be listed. These parameters will be assigned to values during the call. The statements assigned to the defined function may contain a return statement, which can prescribe what object must be returned to the caller.
It is important to note that the variables defined inside the function cannot be accessed from outside (they form a new namespace). The external variables can be accessed from the function if they meet certain criteria. If you define a variable inside the function definition with the name identical to an external variable, then this variable will be shadowed by the new variable and changing it won’t have any effect on the external variable.
The functions are also objects , like objects of the other types shown so far. Although they are defined in a different way than other objects assigned to variable names, a function is actually a variable name. Because of this, a function name can be assigned to another variable name or can be used as an argument.