Nick Coghlan added the comment:
It's mostly pedagogical - similar to "normal functions" vs "generator
functions", folks talk about functions and closures as different things, even
though in Python a closure is just a normal function with one or more
references to cells that were defined in outer scopes.
Having that show up in the repr() then becomes a way of clarifying that some,
but not all, Python function objects are closures, even though closures aren't
represented as a distinct type.
That difference also shows up in the bytecode that creates them (note the
MAKE_FUNCTION vs MAKE_CLOSURE):
>>> def outer():
... x = 1
... def inner_function():
... pass
... def inner_closure():
... return x
...
>>> import dis
>>> dis.dis(outer)
2 0 LOAD_CONST 1 (1)
3 STORE_DEREF 0 (x)
3 6 LOAD_CONST 2 (<code object inner_function at
0x7fade75e5c90, file "<stdin>", line 3>)
9 LOAD_CONST 3 ('outer.<locals>.inner_function')
12 MAKE_FUNCTION 0
15 STORE_FAST 0 (inner_function)
5 18 LOAD_CLOSURE 0 (x)
21 BUILD_TUPLE 1
24 LOAD_CONST 4 (<code object inner_closure at
0x7fade75e5a50, file "<stdin>", line 5>)
27 LOAD_CONST 5 ('outer.<locals>.inner_closure')
30 MAKE_CLOSURE 0
33 STORE_FAST 1 (inner_closure)
36 LOAD_CONST 0 (None)
39 RETURN_VALUE
One particular case where the distinction matters and is known to be genuinely
confusing for new Python users is the late binding behaviour of closures:
lambda: i # closure
lambda i=i: i # not a closure
----------
_______________________________________
Python tracker <[email protected]>
<http://bugs.python.org/issue24056>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com