Variables#

A variable in Python is a name bound to an object. Types belong to objects, not to names; the same name can rebind to a value of a different type at any point. The operator manages variables by controlling scope, lifetime, and mutability, since the language enforces none of these by default.

This page covers binding, scope rules, and the keywords that rebind across scopes. For the types of values a name can hold, see Types. For the operators that act on bindings, see Operators.

Bind#

Assignment binds a name in the current scope. Augmented assignment (+=, *=, etc.) rebinds in place for immutable types and mutates in place for mutable types.

Plain bind.

x = 1

Rebind to a value of a different type; the name re-points, no error.

x = "now a string"

Augmented assignment on an immutable value rebinds the name to a new object.

x += 1            # int is immutable; x points at a fresh int

Augmented assignment on a mutable container mutates in place; the name keeps pointing at the same object.

xs += [4]         # list is mutable; xs.extend in disguise

The walrus := binds inside an expression. Useful in while loops, if conditions, and comprehensions to avoid recomputation.

while (chunk := f.read(4096)):
    process(chunk)

Unpacking#

Multi-bind in one statement; the right-hand side is iterable and the names take its elements in order.

Tuple unpack two names.

x, y = 1, 2

Swap two values without a temporary.

a, b = b, a

Head plus tail with *rest.

first, *rest = [1, 2, 3, 4]

Init plus last with *init.

*init, last = [1, 2, 3, 4]

Use _ for positions the operator does not need.

x, _, z = (1, 2, 3)

Function parameters use *args and **kwargs for variadic positional and keyword arguments.

def f(*args, **kwargs):
    ...

Call-site spread mirrors the parameter form.

f(*[1, 2, 3], **{"name": "x"})

Scope#

Python resolves names by the LEGB rule, applied in order. Local first, then Enclosing, then Global, then Built-in. The first scope that holds the name wins.

        flowchart LR
    L[Local] --> E[Enclosing]
    E --> G[Global]
    G --> B[Built-in]
    
  • Local, names assigned inside the current function.

  • Enclosing, names from any outer function (closures).

  • Global, names assigned at the module top level.

  • Built-in, names from the builtins module (print, len, range).

x = "global"

def outer():
    x = "enclosing"
    def inner():
        print(x)          # looks up local, then enclosing, hits "enclosing"
    inner()

outer()                   # prints "enclosing"

Rebind#

Plain assignment binds in the local scope. To rebind a name in an outer scope, the operator must say so explicitly.

global#

global rebinds at module scope from inside a function.

count = 0

def tick():
    global count
    count += 1            # without `global`, this is a name error

nonlocal#

nonlocal rebinds in the nearest enclosing function (not the module).

def counter():
    n = 0
    def step():
        nonlocal n
        n += 1
        return n
    return step

c = counter()
c(); c(); c()             # 1, 2, 3

Lifetime#

Names live as long as their scope. Local names die when the function returns. Closures keep enclosing names alive for as long as the inner function holds a reference.

CPython reference-counts every object. When the last reference drops, the object is freed immediately. Reference cycles are swept periodically by the cyclic GC (gc module).

import sys
x = [1, 2, 3]
y = x
sys.getrefcount(x)        # 3 (x, y, plus the getrefcount arg)
del y
sys.getrefcount(x)        # 2

References#

  • Types for the values a name can bind to.

  • Operators for assignment and augmented assignment.

  • Functions for function-scope binding, parameters, and closures.

  • Runtime for the memory model that lives behind every binding.

  • Execution model in the Python Language Reference.