我遇到了泡菜问题:我有一个棘手的用例,而且我没有收到我所腌制的对象的副本。如果我从
开始class OneArg(object):
def __init__(self, somearg, *args, **kwargs):
print "In OneArgs's init with args={} and kwargs={}".format(args, kwargs)
self._somearg = somearg
super(OneArg, self).__init__(*args, **kwargs)
class OneArgSubclass(OneArg, OrderedDict):
def __init__(self, *args, **kwargs):
print "In OneArgSubclass's init with args={} and kwargs={}".format(args, kwargs)
super(OneArgSubclass, self).__init__(*args, **kwargs)
def verbose_pickle_dumps (obj):
result = pickle.dumps(obj)
print result
return result
oas = OneArgSubclass("SOMEARG")
oas['spam'] = 'eggs'
oas_red = pickle.loads(verbose_pickle_dumps(oas))
print "oas_red.keys():", oas_red.keys()
这是我得到的输出:
In OneArgSubclass's init with args=('SOMEARG',) and kwargs={}
In OneArgs's init with args=() and kwargs={}
oas.keys(): ['spam']
c__main__
OneArgSubclass
p0
((lp1
(lp2
S'spam'
p3
aS'eggs'
p4
aatp5
Rp6
(dp7
S'_somearg'
p8
S'SOMEARG'
p9
sb.
In OneArgSubclass's init with args=([['spam', 'eggs']],) and kwargs={}
In OneArgs's init with args=() and kwargs={}
oas_red.keys(): []
我可以看到,当我腌制oas时,'spam'/'eggs'键/值对就在那里,_somearg的值也是如此。但请注意,字符串“OrderedDict”不会出现。当我尝试从pickle加载oas时,它不会拾取字符串'SOMEARG',因此字典的内容最终会以_somearg的值结束。
我看了,oas既没有__getinitargs __()也没有__getnewargs __()。如果我使用常规的dict而不是OrderedDict代码可以工作(并且pickle表示看起来非常不同,包括提到'copy_reg'),所以我认为问题可能是pickle和OrderedDict之间的兼容性。但是当我单独使用OrderedDict时,pickle工作正常。
答案 0 :(得分:1)
当您腌制某些东西时,可以使用several different methods来提取数据,以便在unpickling上重新创建对象。您遇到的问题是OrderedDict
定义了其中一个(__reduce__
),但它返回的内容与您的__init__
不兼容 - 因此您需要编写自己的:
def __reduce__(self):
return (self.__class__, (self._somearg, tuple(self.items())))
答案 1 :(得分:0)
您可能希望为您的班级实施__repr__()
方法,如下所示:http://bytes.com/topic/python/answers/781057-pickle-instance-custom-class。
在他们的示例中,他们从OrderedDict
派生了一个类,并以这种方式实现__repr__()
方法
def __repr__(self):
return '{%s}' % ', '.join([': '.join([repr(k),str(v)]) \
for k,v in zip(self.keys(), self.values())])
当班级__init()__
站立时
class OrderedDict(dict):
def __init__(self, d = None):
self._keys = []
if d == None: d = {}
self.update(d)