Python:如何生成n个不同的对象副本

时间:2013-12-08 23:16:58

标签: python copy generator deep-copy

我有一个带有几个字典的对象,其中包含其他对象以及id和对象列表。

每次更改应用于其中一个词组时,生成此对象的n个副本的最pythonic方法是什么?

例如:

class B(object):
    pass

class A(object):

    def __init__(self):
        d = {1: B(), 2: B(), 3: B()}


a = A()
b = [(1, B()), (2, B())]

我想生成两个a的副本,每个副本有一个不同的B实例。如果可能,我想避免使用深度复制。

编辑,因为我被要求更具体:

我正在运行n次计算,每次更改某个子模块的一个参数。我想避免在内存中保存n个子模块副本,因为它是一个非常大的对象,我想避免重新初始化模拟的其他部分。因此,我希望有一个初始化的基础对象,我想在其上做一些小的修改,从而使用不同的参数运行计算n次。

4 个答案:

答案 0 :(得分:0)

A().d永远不会更改,因此创建副本或创建新实例没有区别。

因此,要创建一个A()的新实例,其中包含B()的新的单独实例,只需创建一个新实例:

second_a = A()

可以直接在此新实例上创建实例之间的任何变体。如果创建这样的对象很昂贵,请使用缓存策略以避免重复计算。

答案 1 :(得分:0)

我认为import_fresh_module可以为您提供帮助,根据文档中的说明和您的需求说明。但我不能多说,不够熟练。

答案 2 :(得分:0)

您的示例未将d分配给任何内容,因此当__init__返回时它将丢失。但是评论表明你希望它是A的实例属性;我假设那就是你想要的。我会实现一个copy方法来复制你想要的东西。例如,我相信这符合您指定的标准,至少对于您提供的示例代码:

class B(object):
    pass

class A(object):

    def __init__(self, d=None):
        if d is not None:
            self.d = d
        else:
            self.d = {1: B(), 2: B(), 3: B()}

    def copy(self, updates=None):
        a = type(self)(self.d.copy())
        if updates is not None:
            a.d.update(updates)
        return a


a = A()
b = [(1, B()), (2, B())]
a2 = a.copy(b)

答案 3 :(得分:0)

你可以在这里做一个单独模式的形式,它将缓存'昂贵'位并允许你通过再次调用它来设置变量位来设置不同的参数:

class BigAssThang(object):
    instances={}
    def __new__(cls, ID, *args):
        if ID in cls.instances:
            return cls.instances[ID]
        else:
            # do somthing really big, expensive and immutable...
            cls.instances[ID]=super(BigAssThang, cls).__new__(cls)
            return cls.instances[ID]

    def __init__(self, ID, thing1=None, thing2=None, etc=None):
        # set the parameters...
        # ANY PREVIOUS INSTANCE's PARAMS ARE WIPED OUT!!!
        self.ID=ID
        self.thing1=thing1
        self.thing2=thing2
        self.etc=etc

    def __repr__(self):
        return 'id={} ID: {} thing1: {} thing2: {} etc: {}'.format(
             id(self), self.ID, self.thing1, self.thing2, self.etc) 

使用:

>>> a=BigAssThang(1,'thing 1', {}, [])
>>> a.etc.append(2)
>>> a
id=4481412944 ID: 1 thing1: thing 1 thing2: {} etc: [2]
>>> b=BigAssThang(1,'thing 1', {}, [])
>>> b
id=4481412944 ID: 1 thing1: thing 1 thing2: {} etc: []
>>> a
id=4481412944 ID: 1 thing1: thing 1 thing2: {} etc: []
>>> c=BigAssThang(2,'thing 1', {'a':22}, [1,2,3])
>>> c
id=4481413072 ID: 2 thing1: thing 1 thing2: {'a': 22} etc: [1, 2, 3]
>>> b
id=4481412944 ID: 1 thing1: thing 1 thing2: {} etc: []

知道将参数设置为b后,将其设置为a。它由ID的{​​{1}}参数控制 - 而不是Python变量名。