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 <rep...@bugs.python.org> <http://bugs.python.org/issue24056> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com