Has the cell_contents call for closures in python changed? I understand that func_closure does not work and __closure__
works.
func.__closure__.
Has the cell_contents call for closures in python changed?
__closure__
is, and always has been, a tuple of cells (even back when it was called func_closure
).
Each cell still has a cell_contents
member. But the tuple, of course, does not.
So, what you want is probably one of these:
func.__closure__[0].cell_contents
[cell.cell_contents for cell in func.__closure__]
It's worth noting that the details of __closure__
are undocumented and an implementation-specific feature of the CPython implementation. While the data model defines __closure__
as:
None
or a tuple of cells that contain bindings for the function’s free variables.
… it doesn't say anything about what those cells are, or that they have an attribute named cell_contents
.
But in 3.3+, there's a documented way to get this information, inspect.getclosurevars:
>>> inspect.getclosurevars(func)
ClosureVars(nonlocals={'i': 1}, globals={}, builtins={}, unbound=set())
If you want to know more than what this function returns, you may want to look at how it's implemented in your favorite interpreter (which is probably CPython, given that none of the other major interpreters support 3.3 yet). inspect
is one of those modules that's designed to have helpful, readable source, so the docs link directly to the source code. So you can see how it works—but it's basically what you'd expect; if __closure__
isn't None
, it just creates a dict mapping each cell name in __code__.co_freevars
to the corresponding cell.cell_contents
from the tuple.
If you want to go even deeper, I don't know of any good explanations of the internals of closures (that would make a good blog post, and I'll bet someone's written one… but the best I could find in a quick google is Michael Foord's Nothing is Private: Python Closures (and ctypes), but CPython's source for function objects and code objects is pretty readable if you know C and the Python C API. You might also want to consider looking at PyPy, which tends to be a bit more complicated, but it's all in Python. There's also a brief implementation note in PEP 227, which added closures in Python 2.1, but it doesn't explain much.