这是pickle实例方法的正确方法吗?如果是的话,为什么不在Python 3中呢?

时间:2011-07-05 13:22:15

标签: python-3.x pickle instance-methods

实例方法不能在Python 2或Python 3中自动腌制。

我需要使用Python 3挑选实例方法,并将Steven Bethard的示例代码移植到Python 3:

import copyreg
import types

def _pickle_method(method):
    func_name = method.__func__.__name__
    obj = method.__self__
    cls = method.__self__.__class__
    return _unpickle_method, (func_name, obj, cls)

def _unpickle_method(func_name, obj, cls):
    for cls in cls.mro():
        try:
            func = cls.__dict__[func_name]
        except KeyError:
            pass
        else:
            break
    return func.__get__(obj, cls)

copyreg.pickle(types.MethodType, _pickle_method, _unpickle_method)

这种方法对于酸洗实例方法是否是傻瓜式的?或者有些事情可怕的错误?我用一些模拟类测试了它,一切似乎都有效。

如果什么都不会出错,为什么Python 3中的标准pickle实例方法不可能?

2 个答案:

答案 0 :(得分:0)

我实际上无法在python 3.5.0上重现原始问题,请参阅以下示例。可能值得查看最新版本以查看它是否只是开箱即用: - )

import pickle
import sys

class Foo:

    @staticmethod
    def my_func():
        return 'Foo.my_func'


class Bar:
    pass

if __name__ == '__main__':
    if len(sys.argv) > 1 and sys.argv[1] == 'restore':
        print('loading pickle')
        with open('test.pickle', 'rb') as fp:
            restored = pickle.load(fp)
            print(restored.baz())
    else:
        print('saving pickle')
        b = Bar()
        b.baz = Foo.my_func

        with open('test.pickle', 'w+b') as fp:
            p = pickle.dump(b, fp)
  

(测试)〜/ test $ python test.py

     

保存泡菜

     

(测试)〜/ test $ python test.py restore

     

加载泡菜

     

Foo.my_func

答案 1 :(得分:0)

如果你想挑选类实例(和实例方法),只需使用dill ...

>>> import dill
>>> 
>>> class Foo:
...   def bar(self, x):
...     return self.y + x
...   def zap(self, y):
...     self.y = y
...   y = 1
... 
>>> f = Foo()
>>> f.zap(4)
>>> f.monty = 'python'
>>> 
>>> _f = dill.dumps(f)
>>> del Foo
>>> del f
>>> f = dill.loads(_f)
>>> f.monty
'python'
>>> f.y
4
>>> 
>>> _b = dill.dumps(f.bar)
>>> del f
>>> bar = dill.loads(_b)
>>> bar(4)
8
>>> 
删除类对象时,

dill可以正常工作,如上所示...所以如果你在没有定义类的情况下启动一个新的python会话,或者你改变了类定义,它也可以工作。 dill甚至可以在没有类对象的实例或类实例时使用。如果您想了解如何操作,请查看dill源代码:https://github.com/uqfoundation/dill

另见相关:https://stackoverflow.com/a/21345273/2379433