如何复制python类?

I15*_*159 47 python

deepcopycopy不会复制一个类:

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

>>> B = deepcopy(A)

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

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

>>> A.ARG = 2

>>> B().ARG
>>> 2
Run Code Online (Sandbox Code Playgroud)

这是唯一的方式吗?

B(A):
    pass
Run Code Online (Sandbox Code Playgroud)

Flo*_*ker 45

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

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

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'
Run Code Online (Sandbox Code Playgroud)

您必须小心可变属性值:

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]' (!)
Run Code Online (Sandbox Code Playgroud)


Dav*_*son 20

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

class B(A):
    pass
Run Code Online (Sandbox Code Playgroud)

  • 您也可以使用`type()`来完成它,例如`B = type("B",(A,),{})` (13认同)
  • 除非为B.ARG分配了值,否则继承不会执行所需的操作(ARG值的不受约束). (5认同)
  • @DavidRobinson有了这个答案,设置A.ARG也将改变B.ARG.这是因为ARG实际上并没有出现在B .__ dict__中,所以它在访问时被解析为A的值,而不是在复制发生时. (3认同)

Jam*_*mes 9

您可以使用工厂功能:

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

A = get_A()
B = get_A()
Run Code Online (Sandbox Code Playgroud)


wil*_*dge 5

正如Florian Brucker指出的那样,可变的类属性存在问题。您也不能只deepcopy(cls.__dict__)使用新样式的对象。为了解决这个问题,我做了以下工作。我敢肯定,有足够的决心可以打破这一点。但是,它将在更多情况下起作用。

from copy import deepcopy
from typing import TypeVar

Cls = TypeVar('Cls')


# This type hint is a dirty lie to make autocomplete and static
# analyzers give more useful results. Crazy the stuff you can do
# with python...
def copy_class(cls: Cls) -> Cls:
    copy_cls = type(f'{cls.__name__}Copy', cls.__bases__, dict(cls.__dict__))
    for name, attr in cls.__dict__.items():
        try:
            hash(attr)
        except TypeError:
            # Assume lack of __hash__ implies mutability. This is NOT
            # a bullet proof assumption but good in many cases.
            setattr(copy_cls, name, deepcopy(attr))
    return copy_cls


def test_copy_class():
    class A(object):
        mutable_class_var = []

    ACopy = copy_class(A)

    a = A()
    acopy = ACopy()

    acopy.mutable_class_var.append(1)
    assert a.mutable_class_var == []
    assert A.mutable_class_var == []
    assert ACopy.mutable_class_var == [1]
    assert acopy.mutable_class_var == [1]
Run Code Online (Sandbox Code Playgroud)