Creating functions in Python (Part 3)
Types of address books
We've been talking about different types of address books. Let's use more precise terms.
- Names in a temporary address book are local.
- Names in the permanent address book are global.
A name defined inside a function call has meaning only while that function call is taking place. In this sense, it is local to that function call. In contrast, a name that has meaning outside function calls is global.
Order of name search
- Not inside a user-defined function call: global
- Inside a function call: local, global
When the computer encounters a name and is not in the middle of a call to a user-defined function, what does it do? It looks in the permanent address book. If it is in the middle of a call to a user-defined function, then a temporary address book has been created. It first looks for the name in the temporary address book, and if the name cannot be found there, only then does it look in the permanent address book.
Optional information
Python has statements global
and nonlocal
to change search order.
You can change the search order by giving information about where a name is to be found.
Optional information
More complicated: functions defined inside functions.
In fact it is a bit more complicated when you define functions inside of other functions. We won't be concerned with such functions or with changing search order.
Reusing names
Glimpse of the future
Reusing names can improve clarity.
Good habit
When it affects clarity, reusing names should be avoided.
When it comes to using names more than once in a program, the choice depends on whether the result is correct and whether it is clear. Since in some cases reuse is the better choice, let's look a little more carefully at how it works.
Global: variable, constant, function
Names in the permanent address book refer to variables, constants, and functions. Since constants behave like variables, we'll just look at variables and functions.
Local: variable, constant, function, parameter
Since it is possible to define a function inside a function, possibilities for entries in temporary address books include variables, constants, functions, and parameters, though for this course we'll avoid functions within functions and, like for global names, consider constants and variables together.
Types of reuse:
- Global and global
- Local and local (same address book)
- Local and local (different address books)
- Global and local
We'll first look at ways names can be reused inside the same address book and then what happens when a name appears in two different address books.
Global and global reuse
Observation
The new use of a global name replaces the old use.
We already know what happens when a name is used to store a value and then another value: the old value is lost when the address book is updated with the address of the new variable.
As we'll see in the upcoming examples, the same thing happens when either or both of the global names is the name of a function.
More global and global reuse
In this example, ape
has two global names, first as a variable and then as a function:
ape = 10
def ape(num):
return num
Will we get the value 10 when we print ape
? No. The following code
ape = 10
def ape(num):
return num
print(ape)
gives the output <function ape at 0x7ffb565f6a60>.
But that's not a surprise. Although first the permanent address book listed 10 as the value for x, as soon as the function was defined, the name was no longer assigned to 10 but instead to the function. We can use it as a function, with the result of the function call on 2, ape(2)
, returning the value 2. This can be observed when we run the code
ape = 10
def ape(num):
return num
print(ape)
print(ape(2))
which gives the output
<function ape at 0x7f72f8079ae8> 2
What if instead we used the same name for a function and then a variable? In the following code, bear
appears first in a function definition and then as the name of a variable. Let's see what happens when we try to print bear
. The following code
def bear(num):
return num
bear = 10
print(bear)
gives the output 10.
This time we obtain the value 10, which makes sense, since in the permanent address book, first bear
was given the name of a function, and then afterwards it was changed to store the value 10. What will happen if we try to use bear
as a function? The following code
def bear(num):
return num
bear = 10
print(bear)
print(bear(2))
gives the output
10 Traceback (most recent call last): File "<string>", line 7, in <module> TypeError: 'int' object is not callable
The error message tells us that an int
object is not callable, that is, that bear
is a variable, not a function. This isn't a surprise. The function definition was lost when bear was assigned to an integer value.
In this example, we'll start by using cat
as the name of a function. We can use the function on the input 10, cat(10)
, and obtain the result 10. This is observed when the following code is run
def cat(num):
return num
print(cat(10))
which gives the output 10.
If we then use cat
as the name of a different function, when we use the name in the function call it is the second function, not the first function, that is being used. For example, the following code
def cat(num):
return num
print(cat(10))
def cat(num):
return num + 1
print(cat(10))
gives the output
10 11
Again, this isn't a surprise: the first function was lost as soon as the second function was defined. We expect the same behaviour in any address book, permanent or temporary. For example, consider the following code
def keep(dog):
dog = 4
return dog
print(keep(1))
which gives the output 4.
In this example, dog
is used as a parameter and then as the name of a variable. The value of the parameter is lost when dog
is assigned the value 4. So, running keep(1)
results in 4 being returned, not 1.
Let's consider another example. The following code
def add_on(num):
eel = 10
eel = 3
return num + eel
print(add_on(1))
gives the output 4.
Here eel
is first assigned the value 10 and then a new value 3 is assigned. Again, the old value is lost, so calling the function add(1)
, results in 1 being added to 3, not to 10.
Local and local reuse (same address book)
Observation
The new use of a global name replaces the old use.
Observation
The new use of a local name replaces the old use in the same address book.
To summarize, we have a new observation that matches our old one. That is, whether it is global, in the permanent address book, or local, in a temporary address book, the new use of a name replaces the old use.
Local and local reuse (different address books)
What happens if names are used as local variables in different functions? Our reasoning tells us that using the same name locally in different functions means that the name is used in local address book for function calls, with no interference. Let's see if that is true. Running the code
def one(fox):
return fox + 1
def two(fox):
return fox + 2
print(one(10))
print(two(10))
gives the output
11 12
When fox
is used as a parameter in function one
and in function two
, calling one(10)
should use the parameter in the temporary address book for one
, yielding the expected result of 11, and calling two(10)
should use the parameter in the temporary address book for two
, yielding the expected result of 12.
Running the code
def one(first):
goat = first + 1
return goat
def two(second):
goat = second + 2
return goat
print(one(10))
print(two(10))
gives the output
11 12
We obtain similar behaviour when goat
appears as a local variable in function one
and as a local variable in function two
, where in each case only one of the temporary address books is used.
Let's consider another example. Running the code
def one(hamster):
return hamster
def two(num):
hamster = num + 3
return hamster
print(one(10))
print(two(10))
gives the output
10 13
Not surprisingly, there is no problem using hamster
as a parameter in function one
and as a local variable in function two
, again with only one address book being used at a time.
Observation
The same name can be used for local names in two different functions.