Global scope
New:
- scope
- global scope
Variables and function names are identifiers (and in future you'll learn about other kinds of identifiers). Scope is the area of the source code where an identifier is accessible (can be used).
A variable created outside of functions has global scope. It's accessible within code that's located anywhere, including inside of functions' bodies. (Of course, except for the cases when the call happens earlier than variable's definition). Here's a simple example:
def gen_title(name):
return manner + " the " + name
manner = "Her Majesty"
print(gen_title("Pumpkin"))
Her Majesty the Pumpkin
The function utilizes two identifiers: its own parameter name
and a globally-scoped variable manner
. The value of manner
is read at the time of the call. Since variables can be redefined, another call may end up reading a different value:
def gen_title(name):
return manner + " the " + name
manner = "Her Majesty"
print(gen_title("Pumpkin"))
manner = "Her Excellency"
print(gen_title("Boop"))
Her Majesty the Pumpkin Her Excellency the Boop
Function names are also globally-scoped identifiers. The only way to use a function name identifier is to call the function1. So, a call may be contained in a body of another function. Below, gen_title
contains a call to gen_cute
:
def gen_cute(word):
return "Little Cutey " + word
def gen_title(name):
return manner + " the " + gen_cute(name)
manner = "Her Majesty"
print(gen_title("Pumpkin"))
Her Majesty the Little Cutey Pumpkin
At this point you may be wondering why is this even worth discussing. Variables and functions can be used anywhere, so?.. Well, there exist other cases where the scope of an identifier is not global. The next lesson will explain one. And in the next courses you'll encounter more syntactic structures with limited scope.
Our examples above were rather plain, so let's work on a real problem to further illustrate globally-scoped variables. The task is to calculate the number of months passed between some year and the current year. Open a new repl and write a function months_since
which takes a year as an argument, and returns the number of months between that year and the current year. You need to store the current year as a separate global variable.
Your solution might look like so:
current_year = 2020
def months_since(year):
return (current_year - year) * 12
print(months_since(2003)); # โโผ 204
Since current_year
is globally-scoped, you can write other functions which also use that variable. For example, let's add a weeks_since
function:
def weeks_since(year):
return (current_year - year) * 52
print(weeks_since(2003)); # โโผ 884
And a weeks_until
function:
def weeks_until(year):
return (year - current_year) * 52
print(weeks_until(2031)); # โโผ 572
Now go ahead and, in addition to those 3 functions, write two more:
years_until_abba100
which calculates how many years left until 100th anniversary of ABBA, a Swedish pop supergroup formed in Stockholm in 1972 by Agnetha Fรคltskog, Bjรถrn Ulvaeus, Benny Andersson, and Anni-Frid Lyngstad ๐๐บ.months_until_halley
which calculates how many months left until Halley's comet returns to our solar system in 2061.
Having a common variable outside of functions is fine in small programs. But as soon as your program reaches a few dozen lines, problems might arise:
- It's hard to read the code because you have to jump between three places: variable creation, function definition and function call.
- It's hard to make sure the variable's value was not changed in between the calls, intentionally or by mistake.
- Functions have additional dependencies. Dependencies often lead to difficult bugs.
Try to write functions that only take values via arguments, but not by accessing external variables from the body. This way you, the programmer, have more control. Bugs are still possible, but they'll be easier to fix.
The described properties of scope are specific to Python and the majority of mainstream programming languages. There exist other languages (e.g. Haskell, Eiffel, Newspeak) where scope is more limited and strict. In some of them it is impossible for a function to access outer variables, for example.
Summary:
- Function's body is an isolated scope inaccessible from outside.
return
transports a value, but does not affect the scope.
For now. In future, you'll learn about an advanced use-case: using a function name identifier as if it were a variable.