脱皮有时会使空白的物体 [英] Unpickle sometimes makes blank objects

查看:99
本文介绍了脱皮有时会使空白的物体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用泡菜保存自定义类;类似于下面的代码(尽管在类上定义了一些方法,还有更多的dict等数据).但是,通常在运行此程序时,先进行腌制然后再进行腌制,然后丢失类中的所有数据,就好像我创建了一个新的空白实例一样.

I'm trying to use pickle to save a custom class; something very much like the code below (though with a few methods defined on the class, and several more dicts and such for data). However, often when I run this, pickle and then unpickle, I lose whatever data was in the class, and its as if I created a new blank instance.

import pickle
class MyClass:
    VERSION = 1
    some_data = {}
    more_data = set()

    def save(self,filename):
        with open(filename, 'wb') as f:
            p = pickle.Pickler(f)
            p.dump(self)

    def load(filename):
        with open(filename,'rb') as ifile:
            u = pickle.Unpickler(ifile)
            obj = u.load()
            return obj

我想知道这是否与泡菜课的备忘有关,但我不认为应该这样做.当它不起作用时,我查看生成的文件,它看起来像这样:(显然不可读,但显然不包含任何数据)

I was wondering if this had something to do with the memo of the pickle class, but I don't feel like it should. When it doesn't work, I look at my generated file and it looks something like this: (Obviously not meant to be readable, but it obviously contains no data)


€c__main__
MyClass
q

无论如何,我希望这足以使某人了解这里可能发生的情况或要看的内容.

Anyways, I hope this is enough for someone to understand what might possibly be going on here, or what to look at.

推荐答案

您遇到的问题是您正在使用可变的类变量来保存数据,而不是将数据放入实例变量中.

The problem you're having is that you're using mutable class variables to hold your data, rather than putting the data into instance variables.

pickle模块仅保存直接存储在实例上的数据,而不保存也可以通过self访问的类变量.当您发现未选取的实例没有数据时,这可能意味着该类不再保存上一次运行的数据,因此实例无法再访问它.

The pickle module only saves the data stored directly on the instance, not class variables that can also be accessed via self. When you're finding your unpickled instance have no data, what that probably means is that the class doesn't hold the data from the previous run, so the instances can't access it any more.

以这种方式使用类变量也可能会引起其他问题,因为数据将由该类的所有实例共享!这是一个说明问题的Python控制台会话代码:

Using class variables that way will probably cause you other problems too, as the data will be shared by all instances of the class! Here's a Python console session code that illustrates the issue:

>>> class Foo(object):
        class_var = []
        def __init__(self, value):
            self.class_var.append(value)

>>> f1 = Foo(1)
>>> f1.class_var
[1]
>>> f2 = Foo(2)
>>> f2.class_var
[1, 2]

那可能不是您想要的.但情况变得更糟!

That's probably not what you wanted. But it gets worse!

>>> f1.class_var
[1, 2] 

您认为属于f1的数据已通过创建f2进行了更改.实际上,f1.class_var是与f2.class_var完全相同的对象(也可以直接通过Foo.class_var使用,而完全不需要任何实例).

The data you thought had belonged to f1 has been changed by the creation of f2. In fact, f1.class_var is the very same object as f2.class_var (it is also available via Foo.class_var directly, without going through any instances at all).

因此,使用类变量几乎肯定不是您想要的.而是为该类编写一个__init__方法,该方法创建一个新值并将其保存为实例变量:

So, using a class variable is almost certainly not what you want. Instead, write an __init__ method for the class that creates a new value and saves it as an instance variable:

>>> class Bar(object):
        def __init__(self, value):
            self.instance_var = [] # creates a separate list for each instance!
            self.instance_var.append(value)

>>> b1 = Bar(1)
>>> b1.instance_var
[1]
>>> b2 = Bar(2)
>>> b2.instance_var # doesn't include value from b1
[2]
>>> b1.instance_var # b1's data is unchanged
[1]

Pickle将按照您的期望处理此类.它的所有数据都在实例中,因此,解除锁定时,永远不要以空实例结尾.

Pickle will handle this class as you expect. All of its data is in the instances, so you should never end up with an empty instance when you unpickle.

这篇关于脱皮有时会使空白的物体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆