简体   繁体   English

为什么不能腌制作为对象属性的列表?

[英]Why can't pickle a list that is an attribute of an object?

I am trying to pickle an instance of a custom class, this class has an attribute called "widgets" that contains a list of widget object. 我正在尝试腌制一个自定义类的实例,该类具有一个名为“ widgets”的属性,其中包含小部件对象的列表。 When I pickle my container the list is lost. 当我腌制我的容器时,列表丢失了。 Is it not possible to pickle a list within an object? 是否无法在对象内腌制列表?

import pickle

filename = 'container.pkl'

class Container(object):
    widgets = []

class Widget(object):
    pass

c = Container()
c.name = "My Container"

w = Widget()
w.name = "My Widget"

c.widgets.append(w)

data = open(filename, 'wb')
pickle.dump(c, data)
data.close()

Later I try to unpickle... 后来我试图解开...

# assume I have imported the classes and filename here

data = open(filename, 'rb')
container = pickle.load(data)
data.close()


print container.name # shows the pickled name
print container.widgets # shows []

I have tried pickle and cPickle with the same results. 我尝试了泡菜和cPickle具有相同的结果。

widgets is an attribute of the class Container not an attribute of the instance of the Container class. widgetsContainer 的属性,而不是Container实例的属性。 When you pickled the instance you haven't pickled the class attributes, just the instance attributes. 当您腌制实例时,您没有腌制类属性,仅腌制实例属性。 So when you unpickle it you get just the instance attributes back. 因此,当您释放它时,您只会得到实例属性。

You should read about instance vs. class attributes in the python docs 您应该在python文档中了解实例属性与类属性

If you want to pickle the widgets too, then you should make the list an instance attribute instead of a class attribute. 如果您也想腌制这些小部件,则应将列表设为实例属性而不是类属性。 Here is an example: 这是一个例子:

import pickle

filename = 'container.pkl'

class Container(object):
    def __init__(self, name):
        self.name = name
        self.widgets = []

class Widget(object):
    def __init__(self, name):
        self.name = name

c = Container('My Container')
w = Widget('My Widget')

c.widgets.append(w)

data = open(filename, 'wb')
pickle.dump(c, data)
data.close()

It is definitely possible to pickle List objects within Python. 在Python中腌制List对象绝对是可能的。 It is possible that the custom class you are using may have overridden the __getstate__ and __setstate__ methods, where-in the developer has decided not to pickle the widget list by deleting it from the set of attributes to be pickled/un-pickled for that class. 您正在使用的自定义类可能已经覆盖了__getstate____setstate__方法,在这种情况下,开发人员已决定不通过从该类要腌制/未腌制的属性集中删除它来腌制小部件列表。 。

Refer here for more information. 有关更多信息,请参见此处 It would be good if you can observe the source code for this custom class and check if this indeed the case 如果您可以观察此自定义类的源代码并检查是否确实如此,那将是很好的

The problem is that widgets is a class attribute and wasn't pickled. 问题在于,小部件是一个类属性,没有被腌制。 The script will appear to work if you unpickle in the same session because Container.widgets is already what you want. 如果您在同一会话中打开脚本,该脚本将似乎可以工作,因为Container.widgets已经是您想要的。 It will not work when you start a new session because the Container.widgets will not have been populated. 当您开始新的会话时,它将不起作用,因为将不会填充Container.widgets。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM