有没有一种在python中创建拷贝构造函数的好方法?

时间:2012-05-17 17:36:13

标签: python copy-constructor deep-copy

我意识到与此问题非常相似的问题,虽然不是这样的。

我希望为我的类的构造函数提供一个可选参数,如果它是我的类的实例,将被复制。例如,像(我知道这段代码不起作用!):

class Foo(object):
    def __init__(self, foo=None):
        self.x = None
        self.y = None
        self.z = None

        if foo is not None and isinstance(foo, Foo):
            self = copy.deepcopy(foo)

a = Foo()
a.x = 1
a.y = 2
a.z = 3

b = Foo(a)
print b.x
print b.y
print b.z

我知道有一些实用的解决方案。我可以根据foo的相应属性的值来设置self的每个属性,但这真的很烦人,因为我的类有很多很多属性。或者我可以简单地使用do:

b = copy.deepcopy(a)

......但如果可能的话,我不愿意。我也希望避免覆盖__new__

在python中创建拷贝构造函数真的没有办法吗?

3 个答案:

答案 0 :(得分:16)

我认为这是最狡猾的方式 - 复制工厂方法。

import copy

class Foo(object):
    def __init__(self):
        self.x = None
        self.y = None
        self.z = None
    def copy(self):
        return copy.deepcopy(self)

a = Foo()
a.x = 1
a.y = 2
a.z = 3

b = a.copy()
print b.x
print b.y
print b.z

这在python基本类型中很常见(例如dict.copy)。它不是复制构造函数,但我认为这不是一个非常pythonic的概念!

答案 1 :(得分:1)

执行此操作的一个好方法是创建实例命名空间的顶级副本。

class Tst:
    def __init__(self, somearg):
        if isinstance(somearg, self.__class__):
            self.__dict__ = somearg.__dict__.copy()
        else:
            self.var = somearg
    def echo(self):
        print(self.var)

a = Tst(123)
b = Tst(456)
a.echo()        # gives 123
b.echo()        # gives 456
c = Tst(a)
c.echo()        # gives 123
c.var is a.var  # gives False -> different objects

但是,如果您的班级处理__slots__,请务必小心,因为在这种情况下__dict__可能不存在,因此您可能需要依赖更中性的属性获取机制,例如{{1} }

答案 2 :(得分:0)

可能,因为您可以迭代传递给__init__的源对象上的所有属性,然后setattr() self关注的{{1}} }}。但是,一点也不清楚这将是解决问题的好方法。不是Pythonic,而是全部。