[Python-Dev] Unbinding of methods
M Stefan
mstefanro at gmail.com
Thu Jul 19 18:53:27 CEST 2012
Hey,
As part of pickle4, I found it interesting to add the possibility
of pickling bound functions (instance methods). This is done by
pickling f.__self__ and f.__func__ separately, and then adding
a BIND opcode to tie them together.
While this appears to work fine for python methods (non-builtin), some
issues arise with builtins. These are partly caused because
not all builtin function types support __func__, partly because
not all of them fill __module__ when they should and partly
because there are many (7) types a function can actually have:
ClassMethodDescriptorType = type(??)
BuiltinFunctionType = type(len)
FunctionType = type(f)
MethodType = type(A().f())
MethodDescriptorType = type(list.append)
WrapperDescriptorType = type(list.__add__)
MethodWrapperType = type([].__add__)
AllFunctionTypes = (ClassMethodDescriptorType, BuiltinFunctionType,
FunctionType, MethodType, MethodDescriptorType,
WrapperDescriptorType, MethodWrapperType)
repr(AllFunctionTypes) = (
<class 'classmethod_descriptor'>,
<class 'builtin_function_or_method'>, <class 'function'>,
<class 'method'>, <class 'method_descriptor'>,
<class 'wrapper_descriptor'>, <class 'method-wrapper'>)
I have created a patch at [1], which adds __func__ to some other
function types, as well as:
1) adds AllFunctionTypes etc. to Lib/types.py
2) inspect.isanyfunction(), inspect.isanyboundfunction(),
inspect.isanyunboundfunction()
3) functools.unbind
Note that I am not knowledgeable of cpython internals and therefore
the patch needs to be carefully reviewed.
Possible issues: Should classmethods be considered bound or unbound?
If cm is a classmethod, then should
cm.__func__.__self__ = cm.__self__ or cm.__func__.__self__ = None?
Currently does the latter:
>>> cm.__self__, hasattr(cm,'__self__'), hasattr(cm.__func__,
'__self__')
(<class '__main__.A'>, True, False)
This requires treating classmethods separately when pickling,
so I'm not sure if this is ideal.
Let me know if I should have opened an issue instead. I look
forward to hearing your opinions/suggestions on this matter.
Regards,
Stefan M
[1] https://gist.github.com/3145210
More information about the Python-Dev
mailing list