在实例化时返回不同的对象

时间:2011-07-22 09:57:11

标签: python

当我实例化我编写的特定类时,我给它命名并将几个属性作为__init__的参数。鉴于传递的名称,我的__init__尝试在磁盘上找到适用于该名称的文件,而不是处理传递的其他参数,而是从文件中读取所有这些文件。如果找不到该文件,则使用参数。

现在我想知道,如果我想使用pickle存储整个对象而不是使用我自己的例程来编写文件,我将如何完成加载?我无法在__init__内取消对象,因为已经创建了对象,对吧?

我的一个想法是编写一个我将用于实例化的类方法,如果它存储在磁盘上则返回一个unpickled对象,否则它将使用传递的参数创建一个新对象。

另一个想法是使用__new__而不是将返回对象的类方法,但我不知道这是否是__new__的预期用途。

这些想法是否有用或是否有更好的方法来实现这一目标?

2 个答案:

答案 0 :(得分:4)

使用工厂功能,而不是在__init__中执行此操作。例如:

class Foo(object):
    # whatever

def get_foo(path, *args, **kwargs):
    try:
        obj = pickle.load(open(path))
        if not isinstance(obj, Foo):
            raise TypeError, "%s does not contain a Foo" % path
        return obj
    except IOError as e:
        if e[0] == errno.ENOENT:
            return Foo(*args, **kwargs)
        else:
            raise

答案 1 :(得分:0)

我非常喜欢使用类方法来处理这种事情,因为它将特殊情况逻辑与“标准”类初始化逻辑分开。例如。

class MyClass(object):
    @classmethod
    def load(cls, name, **kargs):
        try:
            state = state_from_file(name) ## your loading code
        except Exception:
            state = kargs
        return cls(name, **state)

    def __init__(self, name, food=None, **kargs):
        self.name = name
        self.food = food

d = MyClass(name='eric', food='spam & eggs')
d = MyClass.load(name='eric', food='spam & eggs')

至于如何坚持你的对象状态......我真的不喜欢使用泡菜;毫无疑问它可行但我发现使用json,yaml等格式显式保存您的实例状态更容易。在平台兼容性,未来校对等方面感觉更安全。无论如何。如果您充分隔离了持久性代码,则可以轻松地将其交换出来。