A function is an object made by a def statement or a
lambda expression.
def runs when it is reached: it builds the function object and binds it
to a name, and the body runs only when the function is called (Language Reference
8.7).
The def statement
funcdef: [decorators] "def" funcname [type_params] "(" [parameter_list] ")"
["->" expression] ":" suite
decorators: decorator+
decorator: "@" assignment_expression NEWLINE
def area(width: float, height: float = 1.0) -> float:
"""Return the area of a rectangle."""
return width * height
A function that ends without return returns None. A function
whose body contains yield is a
generator
function. async def makes a
coroutine function. The
type parameter list in square
brackets makes a generic function (Python 3.12). Python has no overloading: a second
def with the same name replaces the first.
Parameter kinds
def f(pos_only, /, normal, *args, kw_only, **kwargs): ...
| Kind | Position in the list | Passed as |
|---|---|---|
| Positional-only | Before / (3.8, PEP 570) | Position only |
| Positional-or-keyword | The default kind | Position or name |
| Variable positional | *args | Collects extra positional arguments into a tuple |
| Keyword-only | After * or *args (PEP 3102) | Name only |
| Variable keyword | **kwargs | Collects extra keyword arguments into a dictionary |
- A bare
*marks the end of the positional parameters and collects nothing. It must be followed by at least one named parameter. - Among positional parameters, one with a default cannot be followed by one without. Keyword-only parameters may be in any order.
- The names
argsandkwargsare only a convention. - A positional-only name may also appear as a key in
**kwargs, because it cannot clash.
How arguments are bound
At a call (6.3.3), positional arguments fill the positional parameters in order.
Extras go to *args, or raise TypeError. Keyword arguments
fill the matching named parameters, and extras go to **kwargs.
Parameters still unfilled use their defaults. An unfilled parameter with no default
raises TypeError, as does giving a value to the same parameter twice.
def p(a, b=2, *args, c, d=4, **kw):
return a, b, args, c, d, kw
p(1, c=3) # (1, 2, (), 3, 4, {})
p(1, 2, 3, c=9, e=5) # (1, 2, (3,), 9, 4, {'e': 5})
p(*[1, 2], **{"c": 3}) # (1, 2, (), 3, 4, {})
Default values
A default is evaluated once, when the def statement runs, and is then
shared by every call. A mutable default therefore carries changes between calls.
Use None and create the object in the body:
def bad(item, seen=[]):
seen.append(item)
return seen
bad(1) # [1]
bad(2) # [1, 2]: the same list
def good(item, seen=None):
if seen is None:
seen = []
seen.append(item)
return seen
Closures
A nested function can use names from the functions around it. The function object
keeps those variables alive after the outer function returns. They are stored in cells,
visible through __closure__. Rebinding such a name needs
nonlocal.
def make_counter():
n = 0
def increment():
nonlocal n
n += 1
return n
return increment
counter = make_counter()
counter() # 1
counter() # 2
A closure captures the variable, not its current value, so a function made in a loop sees the last value:
late = [lambda: i for i in range(3)]
[f() for f in late] # [2, 2, 2]
fixed = [lambda i=i: i for i in range(3)]
[f() for f in fixed] # [0, 1, 2]
Decorators
A decorator is a callable that receives a function and returns what the name should be bound to (PEP 318). Decorators apply from the bottom up, closest to the function first. Since Python 3.9 a decorator can be any expression (PEP 614).
@f1(arg)
@f2
def func():
pass
# does the same as, except that func is not bound in between
def func():
pass
func = f1(arg)(f2(func))
import functools
def repeat(times):
def decorator(fn):
@functools.wraps(fn)
def wrapper(*args, **kwargs):
for _ in range(times):
result = fn(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def greet():
print("hello")
functools.wraps copies the name and docstringClasses can be decorated the same
way. Common built-in decorators are @staticmethod,
@classmethod and @property, and
functools.cache and functools.singledispatch are in the
standard library.
Function attributes
| Attribute | Meaning |
|---|---|
__name__, __qualname__ | The name, and the dotted path to it (PEP 3155) |
__doc__ | The docstring, or None |
__module__ | The name of the defining module |
__defaults__ | A tuple of positional defaults, or None |
__kwdefaults__ | A dictionary of keyword-only defaults, or None |
__code__ | The compiled body |
__globals__ | The module's namespace |
__builtins__ | The built-in namespace (3.10) |
__closure__ | The cells of captured variables, or None |
__dict__ | Arbitrary attributes set on the function (PEP 232) |
__annotations__, __annotate__ | Its annotations |
__type_params__ | Its type parameters (3.12) |
A function defined in a class becomes a method through the
descriptor protocol. Recursion is
limited, by default to a depth of 1000; sys.setrecursionlimit changes the
limit, and exceeding it raises RecursionError.