[Python-Dev] Unbinding of methods

Richard Oudkerk shibturn at gmail.com
Thu Jul 19 21:51:39 CEST 2012


On 19/07/2012 7:54pm, Antoine Pitrou wrote:
 > Instead of a specific opcode, can't you use a suitable __reduce__
 > magic (or __getnewargs__, perhaps)? We want to limit the number of
 > opcodes except for performance-critical types (and I don't think
 > bound methods are performance-critical for the purpose of
 > serialization).

The one wrinkle is that BuiltinFunctionType is special cased to be 
pickled with save_global, and has no fallback to 
__reduce__/__reduce_ex__/copyreg.  (The C implementation for 
FunctionType *does* have such a fallback, whereas the Python 
implementation doesn't -- see bug http://bugs.python.org/issue14336.)

If the fallback is added for BuiltinFunctionType then "__reduce__ magic" 
should be enough.

The following code works as expected:

import pickle
import copyreg

class A(object):
     def f(self):
         pass
     @classmethod
     def g(cls):
         pass

def f(self):
     pass

ClassMethodDescriptorType = type(A.g)
BuiltinFunctionType = type(len)
FunctionType = type(f)
MethodType = type(A().f)
MethodDescriptorType = type(list.append)
WrapperDescriptorType = type(list.__add__)
MethodWrapperType = type([].__add__)

obj_list = [A.g, len, f, A().f, list.append, list.__add__, [].__add__]

assert ClassMethodDescriptorType is MethodType

def reduce_self(self):
     return getattr, (self.__self__, self.__name__)

def reduce_objclass(self):
     return getattr, (self.__objclass__, self.__name__)

copyreg.pickle(MethodType, reduce_self)
copyreg.pickle(BuiltinFunctionType, reduce_self)
copyreg.pickle(MethodWrapperType, reduce_self)
copyreg.pickle(MethodDescriptorType, reduce_objclass)
copyreg.pickle(WrapperDescriptorType, reduce_objclass)

for obj in obj_list:
     data = pickle.dumps(obj)
     new_obj = pickle.loads(data)
     print('%s\n%s\n' % (obj, new_obj))




More information about the Python-Dev mailing list