For example, in the following bit of Python,
the second line refers to the x
that was defined on the first line.
x = 2 + 2 print 'two plus two is', x
Pretty simple, right? The scoping rules in Python are straightforward, and it's important to understand them well.
There are three main things to remember.
1. All Names are Scoped the Same
The first principle to know about Python
is that names for all kinds of things —
numbers, strings, functions, types, modules —
are treated the same way.
(This may be unlike other languages you've encountered;
for example, in Java and C++,
the variable blerg
and the class blerg
are considered two different things.)
In Python, a name can only refer to one thing at a time.
Another way of looking at this is to say that all names are variables. Here's a program to illustrate this:
spoon = 2 + 2
print spoon
def spoon(x):
return x + 3
print spoon
spoon = 'foo'
print spoon
spoon.
print statements will print.
Then start Python and type in the lines in the above example, one by one.
Compare the results to what you predicted before proceeding.
In the entire example above,
there is only one variable named spoon.
At first, spoon is bound to the value 4.
Then the def spoon statement
causes spoon to be bound to a function.
The number 4 to which spoon was previously bound is gone,
replaced by the function.
Then spoon is bound to a string;
the function is gone, replaced by the string.
2. The Scope of a Name is its Enclosing File, Function, or Class
Each name belongs to a namespace, which is a thing that associates names with their values. (A namespace is sometimes called an "environment" in Scheme.) So, for example:
def genius():
x = 2 + 2
print 'two plus two is', x
When the genius function is called,
it creates its own local namespace
within the namespace
where genius resides.
The second line causes x to be bound to 4 in the local namespace,
and the third line refers to the x in the local namespace.
We would say that the scope of x
is the genius function.
Now let's look at a more interesting example.
Suppose we have a file named example4.py
that contains this program:
x = 2 + 2
def genius():
print 'two plus two is', x
def dummy():
x = 3
print 'two plus two is', x
def gullible(x):
print 'two plus two is', x
genius()
dummy()
print x
genius()
gullible(5)
example4.py.)
The first line creates a variable x
that belongs to the namespace of the file;
its scope is the entire file example4.py.
The genius function creates a namespace,
but that namespace doesn't have an x in it.
When the genius function refers to x,
Python looks for x in the function's namespace,
doesn't find it there,
and then checks the next larger enclosing namespace.
So genius uses the variable x defined at the top.
We could represent this situation in a picture:
genius(),
x refers to the outer variable x.
However, the dummy function
defines its own variable named x.
Any mention of x within the dummy function
will refer to that x.
The second definition of x shadows
the first definition;
the code within the dummy function
cannot see the x that was defined outside.
Calling the genius function
again after dummy
shows that the assignment
to the local variable x in dummy
had no effect on the outer variable x.
dummy(),
the local variable x shadows the outer x.
The gullible function
has an x in its own namespace,
just like dummy.
This x gets assigned whatever value is passed in
as an argument, and it also shadows the outer x.
gullible(5),
the argument x shadows the outer x.
Classes have their own namespaces, too,
though they're a bit more complicated.
For now, all you need to know is that
def and class
are the only keywords that introduce new namespaces.
3. Names Belong to the Namespace Where They're Bound
In Example 4, the assignment x = 3
caused all the occurrences of x in dummy
to refer to a local variable x in dummy's namespace
instead of the x defined at the top of the file.
But x would still be a local variable
throughout dummy
even if x = 3 were moved to the last line of the function.
It doesn't matter where the assignment appears
within the function, or even whether it is executed.
In Python, you can always determine the scope of any name just by looking at the program. The scope of a name does not change while the program is running. (In formal terms, Python is a lexically scoped language.) If a binding for a variable appears anywhere inside a function, that variable name is local to the function.
Given that, have a look at the following example:
x = 1
def kumquat():
x = 5
print x
def gazebo():
print x
# many lines of code...
# many lines of code...
# many lines of code...
x = 5
def hullabaloo(y):
if y > 3:
x = 5
print x
kumquat()
gazebo()
hullabaloo(1)
hullabaloo(6)
example5.py.)
The kumquat function
creates a local variable x in its own namespace,
shadowing the outer variable x.
The line print x
refers to this local x,
so it prints 5.
kumquat(),
the local variable x shadows the outer x.
The gazebo function also has
a local variable x in its namespace,
determined by the fact that an assignment to x
is present in the function.
The local variable x shadows the outer x,
even though the local x is initially not bound to anything.
The line print x
looks for x in the local namespace,
finds that it is not bound to anything,
and so the reference to x is an error
(an UnboundLocalError occurs).
gazebo(),
the local x shadows the outer x
even before it is assigned anything.
Similarly, in hullabaloo,
the variable x is local,
regardless of whether x = 5 is executed.
When we call hullabaloo(1),
the line x = 5 is not executed,
so print x causes an error.
When we call hullabaloo(6),
the line x = 5 is executed,
so print x prints out 5.
All right, let's try a few more.
x = 1
def plethora(y):
if y:
print x
def x(a):
return a * 2
print x
def blubber(y):
if y:
print x
for x in range(10):
print x
def galoshes():
class x:
y = 3
print x
plethora(0)
plethora(1)
blubber(0)
blubber(1)
galoshes()
x is a local variable in all three of these functions.
When plethora(0) is called,
the local variable x is bound to a new function
and then printed out.
When plethora(1) is called,
the initial attempt to print x
executes and causes an error.
When blubber(0) is called,
the local variable x takes on values from 0 to 9
and each of the numbers from 0 to 9 is printed out.
When blubber(1) is called,
the initial attempt to print x
executes and causes an error.
Finally, when galoshes() is called,
the local variable x is bound to a new class
and then printed out.
There are several ways to bind a name to something in Python:
- By assigning to a variable, as in
x = 3. - By receiving an argument, as inside a function with an argument named
x. - By importing a module, as in
import x - By importing a variable, as in
from y import x - By defining a function, as in
def x(foo): ... - By defining a class, as in
class x: ... - By a
forloop, as infor x in y: ... - By an
exceptclause, as intry: ... except x: ...
Any of these, if it appears inside a function, makes the name local to the function.
What do you do if you want to write a function
that assigns to a variable outside the function?
If you write an assignment statement,
that automatically makes the variable local,
so the assignment will have no effect on the outer variable.
But if you use the global keyword
to declare the variable,
that forces the name to refer to the variable at the file level.
x = 2
def foible():
x = x + 1
def spatula():
global x
x = x + 1
print x
foible()
print x
spatula()
print x
global keyword forces a name
to refer to the file-wide namespace.
This example prints 2; then calling foible() produces an error;
then it prints 2, then it prints 3.
The function foible only increments a local x,
whereas spatula increments the global x.
foible(),
only the local variable x has been incremented.
spatula(),
the global variable x has been incremented.
(The word global is slightly inaccurate,
since declaring a variable global
doesn't make it totally global —
it doesn't extend its scope into other files.
Declaring a variable to be global
really means that it belongs to the file's namespace.)
Note that calling a method on an object can also change the object
(if an object can change internally like this,
it is called a mutable object).
A function can modify an outer mutable object by calling a method on it;
calling the method does not create a binding,
and if there are no other bindings,
the variable doesn't have to be declared global.
x = [4]
def igloo():
x.append(3)
def mukluk():
x = [1, 2]
x.append(3)
print x
igloo()
print x
mukluk()
print x
This example prints [4], then [4, 3],
then [4, 3] again.
The igloo function calls the append method
of the global x,
whereas in the mukluk function
x refers to a local variable.
igloo(),
3 has been appended to the list
in the global x.
mukluk(),
3 has been appended to the list
in the local x.
That's it for our discussion of scopes in Python. I hope this all makes more sense to you now.