Suppose I have a function recursive through its closure:
def outer(): def fact(n): return 1 if n == 0 else n * fact(n - 1) return fact
Now I want to serialize the function and restore it using types.FunctionType :
import pickle, marshal, copyreg, types def make_cell(value): return (lambda: value).__closure__[0] def make_function(*args): return types.FunctionType(*args) copyreg.pickle(types.CodeType, lambda code: (marshal.loads, (marshal.dumps(code),))) copyreg.pickle(type((lambda i=0: lambda: i)().__closure__[0]), lambda cell: (make_cell, (cell.cell_contents,))) copyreg.pickle(types.FunctionType, lambda fn: (make_function, (fn.__code__, {}, fn.__name__, fn.__defaults__, fn.__closure__))) buf = pickle.dumps(outer()) fn = pickle.loads(buf)
This works fine for regular closures, but with fact it leads to infinite recursion, as pickle tries to serialize fact within its closure. The usual way to handle recursive data structures in pickle is to memoise the object between construction and initialization, but function objects are immutable, like the t28> tags (tuple) and cells:
>>> cell = (lambda i=0: lambda: i)().__closure__[0] >>> cell.cell_contents = 5 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: attribute 'cell_contents' of 'cell' objects is not writable
Presumably, the language should do something similar when building recursive functions within regular code, since again the function object is not available for placement in its closure before its creation. Is there any magic for creating recursive functions that I miss?