如何复制python类?

时间:2012-03-02 22:06:04

标签: python

来自deepcopy

copy不会复制一个类:

>>> class A(object):
>>>     ARG = 1

>>> B = deepcopy(A)

>>> A().ARG
>>> 1

>>> B().ARG
>>> 1

>>> A.ARG = 2

>>> B().ARG
>>> 2

这是唯一的方式吗?

B(A):
    pass

10 个答案:

答案 0 :(得分:38)

一般来说,继承是正确的方法,正如其他海报已经指出的那样。

但是,如果你真的想要使用不同的名称重新创建相同的类型而没有继承,那么你可以这样做:

class B(object):
    x = 3

CopyOfB = type('CopyOfB', B.__bases__, dict(B.__dict__))

b = B()
cob = CopyOfB()

print b.x   # Prints '3'
print cob.x # Prints '3'

b.x = 2
cob.x = 4

print b.x   # Prints '2'
print cob.x # Prints '4'

您必须小心使用可变属性值:

class C(object):
    x = []

CopyOfC = type('CopyOfC', C.__bases__, dict(C.__dict__))

c = C()
coc = CopyOfC()

c.x.append(1)
coc.x.append(2)

print c.x   # Prints '[1, 2]' (!)
print coc.x # Prints '[1, 2]' (!)

答案 1 :(得分:18)

正如你所推测的那样,“复制”一个类的正确方法是继承:

class B(A):
    pass

答案 2 :(得分:8)

您可以使用工厂功能:

def get_A():
    class A(object):
        ARG = 1
    return A

A = get_A()
B = get_A()

答案 3 :(得分:2)

我认为你在这里误解了静态变量的含义。每个在方法之外声明变量而不是self.some_thing形状的变量,变量都将被视为类的静态变量(就像你的ARG变量一样)。因此,更改静态变量的类的每个对象(实例)都将导致同一类中所有其他对象的更改。深度复制确实在这里完成了工作。

答案 4 :(得分:2)

正如Florian Brucker所指出的,可变类属性存在问题。您也不能只对新样式对象$ tr '_' ' ' < test_file.tsv mg.reads.per.gene bcsZ A1.tsv contig 21128 476 mg.reads.per.gene bcsZ A1.tsv contig 3712 1774 mg.reads.per.gene bcsZ A2.tsv contig 38480 184 。为了解决这个问题,我已经做了以下工作。我确信有足够的人可以打破这个。但是,它会在更多情况下起作用。

deepcopy(cls.__dict__)

答案 5 :(得分:2)

要复制具有__slots__属性的类,此功能会有所帮助:-)

def copy_class(c,name=None):
    if not name: name = 'CopyOf'+c.__name__
    if hasattr(c,'__slots__'):
        slots = c.__slots__ if type(c.__slots__) != str else (c.__slots__,)
        dict_ = dict()
        sloted_members = dict()
        for k,v in c.__dict__.items():
            if k not in slots:
                dict_[k] = v
            elif type(v) != types.MemberDescriptorType:
                sloted_members[k] = v
        CopyOfc = type(name, c.__bases__, dict_)
        for k,v in sloted_members.items():
            setattr(CopyOfc,k,v)
        return CopyOfc
    else:
        dict_ = dict(c.__dict__)
        return type(name, c.__bases__, dict_)

答案 6 :(得分:1)

创建自己的构造函数,并重复创建原始类的方式:

class MyClass(object):
    def __init__(self, **kw):
        self.kw = kw
        self.__dict__.update(kw)

    def copy(self):
        return MyClass(**self.kw)

我会尽量避免在第一时间复制对象。


旁注:您也可以做到:

B = deepcopy(A)
B.__dict__ = deepcopy(A.__dict__)

但这可能是非常错误的,你不应该这样做。 编辑:实际上AttributeError: 'dictproxy' object has no attribute 'update'根据OP

答案 7 :(得分:0)

一种简单的方法是将类放入模块中,并在每次需要新副本时重新加载它。我认为这涉及可变项,因为重新加载会重新创建所有内容。

答案 8 :(得分:0)

这是在所有级别进行复制的解决方案:

#for windows use dill teh same way

import pickle
copy = lambda obj: pickle.loads(pickle.dumps(obj))

问题是:

class A: a = 1
x = A()
y = x
x.a = 5
print(y.a) #return's 5

带副本:

class A:a = 1
x = A()
y = copy(x)
x.a = 5
print(y.a) #return 1

您可以复制所需的任何内容,而不仅仅是类实例或类

答案 9 :(得分:-1)

如果你想创建另一个类的实例,那么只需创建它:

 >>> class A(object):
...    ARG=1
... 
 >>> a = A()
 >>> A().ARG
 1
 >>> b = A()
 >>> b.ARG
 1
 >>> a.ARG=2
 >>> b.ARG
 1