What exactly are the Python scoping rules?
If I have some code:
code1
class Foo:
code2
def spam.....
code3
for code4..:
code5
x()
Where is x
found? Some possible choices include the list below:
- In the enclosing source file
- In the class namespace
- In the function definition
- In the for loop index variable
- Inside the for loop
Also there is the context during execution, when the function spam
is passed somewhere else. And maybe lambda functions pass a bit differently?
There must be a simple reference or algorithm somewhere. It's a confusing world for intermediate Python programmers.
Python resolves your variables with -- generally -- three namespaces available.
There are two functions:
globals
andlocals
which show you the contents two of these namespaces.Namespaces are created by packages, modules, classes, object construction and functions. There aren't any other flavors of namespaces.
In this case, the call to a function named
x
has to be resolved in the local name space or the global namespace.Local in this case, is the body of the method function
Foo.spam
.Global is -- well -- global.
The rule is to search the nested local spaces created by method functions (and nested function definitions), then search global. That's it.
There are no other scopes. The
for
statement (and other compound statements likeif
andtry
) don't create new nested scopes. Only definitions (packages, modules, functions, classes and object instances.)Inside a class definition, the names are part of the class namespace.
code2
, for instance, must be qualified by the class name. GenerallyFoo.code2
. However,self.code2
will also work because Python objects look at the containing class as a fall-back.An object (an instance of a class) has instance variables. These names are in the object's namespace. They must be qualified by the object. (
variable.instance
.)From within a class method, you have locals and globals. You say
self.variable
to pick the instance as the namespace. You'll note thatself
is an argument to every class member function, making it part of the local namespace.See Python Scope Rules, Python Scope, Variable Scope.
Essentially, the only thing in Python that introduces a new scope is a function definition. Classes are a bit of a special case in that anything defined directly in the body is placed in the class's namespace, but they are not directly accessible from within the methods (or nested classes) they contain.
In your example there are only 3 scopes where x will be searched in:
spam's scope - containing everything defined in code3 and code5 (as well as code4, your loop variable)
The global scope - containing everything defined in code1, as well as Foo (and whatever changes after it)
The builtins namespace. A bit of a special case - this contains the various Python builtin functions and types such as len() and str(). Generally this shouldn't be modified by any user code, so expect it to contain the standard functions and nothing else.
More scopes only appear when you introduce a nested function (or lambda) into the picture. These will behave pretty much as you'd expect however. The nested function can access everything in the local scope, as well as anything in the enclosing function's scope. eg.
Restrictions:
Variables in scopes other than the local function's variables can be accessed, but can't be rebound to new parameters without further syntax. Instead, assignment will create a new local variable instead of affecting the variable in the parent scope. For example:
In order to actually modify the bindings of global variables from within a function scope, you need to specify that the variable is global with the global keyword. Eg:
Currently there is no way to do the same for variables in enclosing function scopes, but Python 3 introduces a new keyword, "
nonlocal
" which will act in a similar way to global, but for nested function scopes.x is not found as you haven't defined it. :-) It could be found in code1 (global) or code3 (local) if you put it there.
code2 (class members) aren't visible to code inside methods of the same class — you would usually access them using self. code4/code5 (loops) live in the same scope as code3, so if you wrote to x in there you would be changing the x instance defined in code3, not making a new x.
Python is statically scoped, so if you pass ‘spam’ to another function spam will still have access to globals in the module it came from (defined in code1), and any other containing scopes (see below). code2 members would again be accessed through self.
lambda is no different to def. If you have a lambda used inside a function, it's the same as defining a nested function. In Python 2.2 onwards, nested scopes are available. In this case you can bind x at any level of function nesting and Python will pick up the innermost instance:
fun3 sees the instance x from the nearest containing scope, which is the function scope associated with fun2. But the other x instances, defined in fun1 and globally, are not affected.
Before nested_scopes — in Python pre-2.1, and in 2.1 unless you specifically ask for the feature using a from-future-import — fun1 and fun2's scopes are not visible to fun3, so S.Lott's answer holds and you would get the global x:
The scoping rules for Python 2.x have been outlined already in other answers. The only thing I would add is that in Python 3.0, there is also the concept of a non-local scope (indicated by the 'nonlocal' keyword). This allows you to access outer scopes directly, and opens up the ability to do some neat tricks, including lexical closures (without ugly hacks involving mutable objects).
EDIT: Here's the PEP with more information on this.
Actually, a concise rule for Python Scope resolution, from Learning Python, 3rd. Ed.. (These rules are specific to variable names, not attributes. If you reference it without a period, these rules apply.)
LEGB Rule
Local — Names assigned in any way within a function (
def
orlambda
), and not declared global in that functionEnclosing-function — Names assigned in the local scope of any and all statically enclosing functions (
def
orlambda
), from inner to outerGlobal (module) — Names assigned at the top-level of a module file, or by executing a
global
statement in adef
within the fileBuilt-in (Python) — Names preassigned in the built-in names module:
open
,range
,SyntaxError
, etcSo, in the case of
The
for
loop does not have its own namespace. In LEGB order, the scopes would bedef spam
(incode3
,code4
, andcode5
)def
)x
declared globally in the module (incode1
)?x
in Python.x
will never be found incode2
(even in cases where you might expect it would, see Antti's answer or here).In Python,
If a variable can't be found in the current scope, please refer to the LEGB order.