在Python 3中如何将未绑定的方法进行Pickling?

9
我想在Python 3.x中对一个未绑定的方法进行pickle。我遇到了这个错误:
>>> class A:
...     def m(self):
...         pass
>>> import pickle
>>> pickle.dumps(A.m)
Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    pickle.dumps(A.m)
  File "C:\Python31\lib\pickle.py", line 1358, in dumps
    Pickler(f, protocol, fix_imports=fix_imports).dump(obj)
_pickle.PicklingError: Can't pickle <class 'function'>: attribute lookup builtins.function failed

有没有人对此有经验?


注意:在Python 2.x中,默认情况下也无法pickle未绑定的方法;我以某种奇怪的方式在那里做到了这一点:我使用copy_reg模块为MethodType类编写了一个reducer,它涵盖了绑定和未绑定的方法。但是reducer仅解决了绑定方法的情况,因为它依赖于my_method.im_self。神秘地是,这也导致Python 2.x能够pickle未绑定的方法。这在Python 3.x上不会发生。

1个回答

7
这是不可能直接完成的,因为在Python 3中,无绑定方法类型已经不存在了:它只是一个函数。
>>> print (type (A.m))
<class 'function'>

Python函数不绑定到类,所以仅从表达式结果无法确定A.m属于哪个类。

根据您的需求,对(类,方法名称)元组进行pickle/unpickle可能已经足够了:

>>> print (pickle.loads (pickle.dumps ((A, 'm'))))
... (<class '__main__.A'>, 'm')

您可以通过使用getattr()方法轻松地从这里获取函数:

>>> cls, method = pickle.loads (pickle.dumps ((A, 'm')))
>>> print (getattr (cls, method))
... <function m at 0xb78878ec>

1
你是说在Python 3中,如果给定一个未绑定的方法,就无法知道该方法是在哪里定义的? - Ram Rachum
4
好的。尝试声明两个类,并将其中一个类的一个方法分配给另一个类(B.m = A.m)。然后,B.mA.m将相等(实际上是相同的),因此无法确定您是在B还是在A中查找该方法。 - user319799

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接