__getinitargs__ 的 Python 3 替代方案

pev*_*gam 4 python pickle python-3.x

__init__在 Python 3 的 unpickling 期间,是否有足够短的方法来调用类的构造函数?这样做的通常方法是__getinitargs__像这样使用

from __future__ import print_function
import pickle

class Car:

    def __init__(self, model, number):
        self.model = model
        self.number = number
        print("constructed with", model, number)
        # many other things to do

    def __getstate__(self):
        # intentionally returns None
        pass

    def __setstate__(self, state):
        pass

    def __getinitargs__(self):
        # save some information when pickling
        # (will be passed to the constructor upon unpickling)
        return self.model, self.number

c = Car("toyota", 1234)
d = pickle.loads(pickle.dumps(c))
print("reconstructed with", d.model, d.number)
Run Code Online (Sandbox Code Playgroud)

但是,__getinitargs__在新样式类中将被忽略,并且在 Python 3+ 中,所有类只能是新样式类。有__getnewargs__但它只会将参数传递给不同的__new__类方法。上述说明性示例的 python 2 调用将导致

>> constructed with toyota 1234
>> constructed with toyota 1234
>> reconstructed with toyota 1234
Run Code Online (Sandbox Code Playgroud)

而 python 3 调用会出错

>> constructed with toyota 1234
Traceback (most recent call last):
  File "test.py", line 26, in <module>
    print("reconstructed with", d.model, d.number)
AttributeError: 'Car' object has no attribute 'model'
Run Code Online (Sandbox Code Playgroud)

并忽略该__getinitargs__方法。

我认为 Python 3 在这方面不会轻易倒退,所以希望我遗漏了一些明显的东西。

编辑:替换__getinitargs____getnewargs__并不能解决问题。

use*_*ica 5

如果你想pickle通过调用来解开你的对象Car(self.model, self.number)__init__以与正常调用相同的方式进行初始化Car,然后告诉它在__reduce__方法中这样做:

def __reduce__(self):
    return (Car, (self.model, self.number))
Run Code Online (Sandbox Code Playgroud)

演示