[Python-Dev] Unbinding of methods

M Stefan mstefanro at gmail.com
Thu Jul 19 18:53:27 CEST 2012


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(),
  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__, 
     (<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.

   Stefan M

[1] https://gist.github.com/3145210

More information about the Python-Dev mailing list