A Python variable is a name bound to an object. Names have no type and are not declared. A name's scope is worked out by the compiler from where the name is bound. This page follows section 4.2 of the Language Reference.
Names and objects
Assignment binds a name to an object and never copies it. Two names can refer to one object, so a change made through one is seen through the other. Rebinding a name affects only that name.
a = [1, 2]
b = a # b and a are the same list
b.append(3)
a # [1, 2, 3]
b = [9] # rebinds b; a is unchanged
a # [1, 2, 3]
Function arguments are passed the same way. The parameter is a new name bound to the caller's object.
What binds a name
These constructs bind a name (4.2.1):
| Construct | Example |
|---|---|
| Assignment, augmented and annotated assignment | x = 1, x += 1, x: int = 1 |
| Assignment expression | (x := 1) |
| Function parameters | def f(x): ... |
| Function and class definitions | def x(): ..., class x: ... |
for target | for x in y: ... |
as in with, except and except* | with f() as x: ... |
Capture patterns and as patterns in match | case [x, y]: ... |
import statements | import x, from m import x |
type statements and type parameter lists | type x = int, def f[x](): ... |
del (counted as binding, although it unbinds) | del x |
from m import * binds every public name of the module, and is allowed only
at module level. A name bound anywhere in a block counts as bound in the whole of that
block.
Blocks and scopes
A block is a piece of code run as a unit: a module, a function body, or a
class body (4.1). A script file, a string passed to exec() and each
command at the interactive prompt are blocks too. if, for,
while, with and try do not create a scope, so a
name bound inside them is still bound afterwards.
| Kind of variable | Meaning |
|---|---|
| Local | Bound in this block, and not declared global or nonlocal |
| Global | Bound at module level, or declared global. Module-level names are both local and global |
| Free | Used in this block but not bound in it, and found in an enclosing function |
Name resolution: LEGB
A name used in a block is looked up in the nearest scope that binds it. The order is often called LEGB:
- Local: the current function.
- Enclosing: any enclosing functions, innermost first.
- Global: the current module's namespace.
- Built-in: the
builtinsmodule.
A name found nowhere raises NameError. Class bodies are special and are
covered below.
x = "global"
def outer():
x = "enclosing"
def inner():
return x # finds outer's x
return inner()
outer() # 'enclosing'
len # found in built-ins
UnboundLocalError
Scope is decided at compile time. If a name is bound anywhere in a function, every use of it in that function is local, even before the binding runs:
count = 0
def f():
print(count) # UnboundLocalError
count = 1
count local to the whole functionLookups happen when the code runs
The compiler decides which scope a name belongs to, but its value is read at run time. A global can change after the function that uses it is defined (4.2.6):
i = 10
def f():
return i
i = 42
f() # 42
i when it is calledglobal and nonlocal
By default, binding a name in a function makes it local. A declaration changes that (7.12, 7.13):
global_stmt: "global" identifier ("," identifier)*
nonlocal_stmt: "nonlocal" identifier ("," identifier)*
total = 0
def add():
global total
total += 1
def make_counter():
n = 0
def inc():
nonlocal n
n += 1
return n
return inc
global rebinds a module-level name, and nonlocal rebinds a name in an enclosing functionThe declaration is needed only to rebind a name. Reading a name from an outer scope
needs no declaration, and neither does changing an outer object's contents. The
compiler reports these as SyntaxError:
- Using or assigning a name in a block before its declaration.
- Declaring a function's parameter as
globalornonlocal. - Annotating a name that is declared
globalornonlocal. nonlocalat module level.nonlocalfor a name with no binding in an enclosing function. The compiler looks only in functions, so the name cannot be a global.
global at module level is allowed but does nothing. A
global declaration applies only to the block it is in, so a string
passed to exec does not inherit it.
Comprehension scopes
A comprehension or generator expression has its own scope, so its loop variable does
not leak (6.2.6). There is one exception: the iterable of the leftmost
for is evaluated in the enclosing scope, and is then passed in.
x = "outer"
squares = [x * x for x in range(3)]
x # 'outer': the loop variable stayed inside
y = 2
[y for y in range(y)] # [0, 1]: range(y) uses the outer y
An assignment expression in a comprehension is different: it binds in the scope that contains the comprehension (PEP 572). It cannot rebind the comprehension's own loop variable, cannot appear in an iterable expression, and cannot appear in a comprehension in a class body.
[(last := n) for n in range(3)]
last # 2
last is bound outside the comprehensionSince Python 3.12 CPython inlines list, dictionary and set comprehensions (PEP 709). They are faster and no longer appear as frames in tracebacks, but scoping is unchanged.
Class scope
A name bound in a class body is visible only in the class body itself. It does not
reach the methods, and it does not reach comprehensions inside the class, apart from
their leftmost iterable (4.2.2). Inside a method, use self.name or the
class name.
class A:
a = 42
b = list(a + i for i in range(10)) # NameError: a is not visible
c = [i for i in range(a)] # valid: leftmost iterable
def f(self):
return a # NameError, unless a global a exists
Unlike a function, a class body falls back to the global namespace for a name that is bound in the class but has not been assigned yet.
Annotation scopes
Annotations, type parameter lists and type statements run in
annotation scopes (4.2.3, Python 3.12). They behave like function scopes,
with these differences:
- They can see the enclosing class's names, which ordinary nested scopes cannot.
- They cannot contain
yield,awaitor:=. - Names they define cannot be rebound by
nonlocalin an inner scope.
Most are lazily evaluated: the expression does not run until something asks for its value (4.2.4). See Type hints.
Built-ins
The built-in functions and types live in the builtins module, and the
last step of name lookup searches it. Built-in names are not keywords, so a program can
rebind them, as with print = 1. That hides the built-in for the rest of
the module. To change a built-in globally, import builtins and set the
attribute. __builtins__ is an implementation detail, and programs should
not use it (4.2.5).
Namespaces as objects
| Call | Result |
|---|---|
globals() | The module's namespace dictionary |
locals() | At module level, the same dictionary. In a class body, the class namespace. In a function, a new snapshot on each call since Python 3.13 (PEP 667) |
vars(x) | x.__dict__ |
dir(x) | A sorted list of names |
eval() and exec() run code in the namespaces they are given,
or the caller's if not. Free variables in that code are resolved in the global
namespace, not in the enclosing function (4.2.6). To collect the results of
exec(), pass your own dictionary.
del x removes the binding. Using the name afterwards raises
NameError, or UnboundLocalError in a function.