在Python中保存和加载类

1 投票
1 回答
816 浏览
提问于 2025-04-17 22:31

我正在尝试使用pickle来保存和加载一些类。在我的项目中,有些类的变量包含了列表、字典和其他类的元组。当我加载保存的类时,里面的类变得不一样了。我找到了一篇关于静态方法__new__的很棒的教程,在这里。我写了以下代码。当执行加载函数时,我得到了3个类1的实例和2个类2的实例。这是为什么呢?

import pickle


def saveclass(obj):
    f = file(obj.name, 'wb')
    pickle.dump(obj, f, -1)
    f.close()


def loadclass(name):
    f = file(name, 'rb')
    retclass = pickle.load(f)
    f.close()
    return retclass


class basicclass(object):

    def __new__(cls, *args, **kw):
    instances = cls.instances
    obj = object.__new__(cls, *args, **kw)
    if obj in instances:
        return instances[instances.index(obj)]
    else:
        instances.append(obj)
        return obj


class class1(basicclass):
    instances = []

    def __init__(self, name):
    basicclass.__init__(self)
    self.name = name


class class2(basicclass):
    instances = []

    def __init__(self, name, otherclass):
    basicclass.__init__(self)
    self.name = name
    self.otherclass = otherclass


c1 = class1("class1")
c2 = class2("class2", c1)

print c1.name
print c2.name, 'has', c2.otherclass.name
print c2.name, "'s 'inside' class is c1:", c2.otherclass == c1

print "Class1 instances"
for inst in c1.instances:
    print inst.name, ':', inst

print "Class2 instances"
for inst in c2.instances:
    print inst.name, ':', inst

print 'saving classes'
saveclass(c1)
saveclass(c2)


print 'Resetting classes'
c1 = None
c2 = None

print 'Reloading classes'

c1 = loadclass("class1")
c2 = loadclass("class2")


print c1.name
print c2.name, 'has', c2.otherclass.name
print c2.name, "'s 'inside' class is c1:", c2.otherclass == c1

print "Class1 instances"
for inst in c1.instances:
    print inst.name, ':', inst

print "Class2 instances"
for inst in c2.instances:
    print inst.name, ':', inst

输出:

> class1 
> class2 has class1 
> class2 's 'inside' class is c1: True 
> Class1 instances 
> class1 : <__main__.class1 object at 0xb7302a8c> 
> Class2 instances 
> class2 : <__main__.class2 object at 0xb7302a2c> 
> saving classes
> Resetting classes
> Reloading classes
> class1
> class2 has class1
> class2 's 'inside' class is c1: False 
> Class1 instances 
> class1 : <__main__.class1 object at 0xb7302a8c>
> class1 : <__main__.class1 object at 0xb72fe10c> 
> class1 : <__main__.class1 object at 0xb72fe1ac>
> Class2 instances 
> class2 : <__main__.class2 object at 0xb7302a2c>
> class2 : <__main__.class2 object at 0xb72fe18c>

1 个回答

3

我想到两种可能性:

  1. 你想在进行“打包”和“解包”时保持对象的身份。一个已经存在的类的对象有一个特殊的标识符。如果在解包时这个对象已经存在,就会重用它。这里有一个例子,它使用了 __new__ 来检查对象是否已经存在。你也可以在使用json时这样做。不过,如果对象的状态是可变的,那就会出现问题,因为加载旧状态会更新这些对象。

  2. 使用相同的序列化工具来进行打包和解包。不要仅仅使用 dumpload,而是要使用相同的 PicklerUnpickler

我觉得这个问题应该在别的地方已经有人回答过了。也许你可以试着搜索一下“对象身份”、“序列化”等关键词,看看能找到什么答案。

撰写回答