Functions (scope)
We have seen how functions can organize and structure code, they can further be nested within one another. As we learn how nesting works, we will simultaneously learn the concept of scope, particularly as it pertains to functions.
Scope refers to the context in which variables and functions are defined and accessed. There are generally two types of scope: local and global.
Local scope pertains to variables and functions defined within a
specific function or block of code, meaning they can only be
accessed and modified within that context. On the other hand,
global scope refers to variables and functions defined outside
of any specific function, making them accessible throughout
the entire program.
The code editor below shows an example of scope by way of
having two functions with the same name,
helper
; one is defined in global scope,
while the other is defined in local scope.
- helper (1st): The first
helper
function is defined at the top level of the script, outside of any other functions. This means it is in the global scope and can be accessed from anywhere in the script. - helper (2nd): In contrast, the second
helper
function is defined within the scope of theprint_statement
function, making it a local function toprint_statement
.
Both of these functions are designed to take a single string argument,
x
, and return a new string that appends a specific
beverage name to the original string. The global helper
function adds "tea" to the input string, while the local
helper
function, defined inside print_statement
,
adds "latte" instead.
When the print_statement
function is called, it in
turn calls its local helper
function, passing the
string "please enjoy your " as the argument. This results in
the local helper
function returning the string
"please enjoy your latte", which is then returned by
print_statement
. It is important to note that
within the scope of print_statement
, the local
helper
function shadows the global one, meaning
that any calls to helper
inside
print_statement
will refer to the local version,
not the global one.
Now lets imagine we have this code:
def print_statement():
def helper(x):
return x + "latte"
return helper("please enjoy your ")
def another_print_statement():
return helper("don't forget your ")
If we attempt to run the another_print_statement
function,
the interpreter will throw an error, indicating that it is unable to
locate the specified function. The error message is provided below
for reference. Since nested functions are local in
scope to the enclosing function and are not visible or accessible
from outside. This issue arises due to the interpreter's inability
to access the helper
function as it is nested inside
print_statement
.
NameError: name 'helper' is not defined
Abstraction
Before we close up this section on functions. Let's talk about the last concept introduced in the definition we gave for a function: abstraction. Abstraction is a concept that is often used in programming, but it can be difficult to understand. In the context of functions, abstraction refers to the idea that we can use a function without knowing how it works. We can think of a function as a black box that takes in some input and returns some output. As long as we know both the input and the output (this is why knowing the input and output types is important as well), then we don't necessarily need to know what happens inside the function to use it.
While this may seem like a counter-productive concept. After all, wouldn't we want to understand what is going on within the function? The answer is yes, but not necessarily right away. Abstraction allows us to use functions without worrying about the details of how they work. For example, we may import a function from a library and use it in our code without knowing how it works. This allows us to focus on the higher-level aspects of our code, such as how we may best utilize the function to improve our code.
At a later time, if this function becomes a bottleneck in our code, we can then dive into the details of how it works and optimize it. Not needing to do so right away allows us to build more complex programs without getting bogged down. In essence, it allows us to build on top of the work of others.
Practice Question
Consider the nested functions below. Identify which string will be
returned when we run the another_print_statement
function?
def helper(x):
return x + "tea"
def print_statement():
def helper(x):
return x + "latte"
return helper("please enjoy your ")
def another_print_statement():
return helper("don't forget your ")
score: 0%