为什么类的深层复制不保留属性?

时间:2014-05-07 16:47:36

标签: python copy deep-copy

在下面的示例中,我深入学习了一个基类并弄乱了副本的属性。为什么这会弄乱原始类的属性?有什么方法可以避免这种情况吗?我正在使用的当前代码结构不支持多继承,所以我真的希望能够以某种方式复制该类。

>>> class Base(object):
...    foo = "bar"
... 
>>> base_copy = copy.deepcopy(Base)
>>> del base_copy.foo
>>> 
>>> base_again = copy.deepcopy(Base)
>>> hasattr(base_again, 'foo')
False
>>> 

3 个答案:

答案 0 :(得分:3)

copy()deepcopy()旨在复制对象而不是类。传递类时,将返回原始类。

Python documentation说:

  

此模块不复制模块,方法,堆栈跟踪,堆栈帧,文件,套接字,窗口,数组或任何类似类型等类型。它通过返回原始对象来“复制”函数和类(浅和深);这与pickle模块处理它们的方式兼容。

确实在使用您的代码进行测试时,我们有:

In [8]: base_copy is Base
Out[8]: True

您可以尝试按照其他答案中的建议弄乱type(),但它非常hackish。

你可以做到

class B(A):
    pass

这是我能想到的最接近的副本。

答案 1 :(得分:1)

copy documentation中所述:

  

此模块不复制模块,方法,堆栈跟踪等类型,   堆栈框架,文件,套接字,窗口,数组或任何类似的类型。它   通过返回“复制”函数和类(浅和深)   原始对象不变

您可以尝试使用metaclasses

class Base(object):
    foo = "bar"

# Create a new class called `base_copy` with attributes and base classes 
# from Base without inheriting from Base
base_copy = type('base_copy', Base.__bases__, dict(Base.__dict__))
# Will delete attribute on `base_copy` class
del base_copy.foo

base_again = type('base_again', Base.__bases__, dict(Base.__dict__))

print(hasattr(base_again, 'foo')) # True

您可以尝试使用deepcopy对象上的dict(Base.__dict__)复制listdict等对象。

答案 2 :(得分:0)

定义构造函数中的所有变量。 您可以创建一个新的构造函数,该构造函数根据提供的参数决定应该在类的对象中存在哪些所有字段。

Class Foo:
     def __init__(self):
        self.param0 = 0
        self.param1 = 0
     def __init__(self,i):
        if i == 0:
            self.param0 = 0
        if i == 1: 
            self.param1 = 1