为什么 Python 的 class 对象的 deepcopy() 共享 class 变量?

Why is Python's deepcopy() of a class-object sharing class-variables?

我正在使用 deepcopy 制作 Python class 的深拷贝,并更改复制对象的 class 变量。由于某种原因,复制的原始class的class变量也被更改。这是为什么?

当我用 'type' syntax 创建 class 时似乎没有发生。

import copy

class Test:
    a = 0

print(Test.a) # 0
b = copy.deepcopy(Test)
b.a = 1
print(Test.a) # 1 - why?

c = type('Test2', (Test,), {'a': 2})
print(Test.a) # still 1

您复制了 class 定义而不是实例本身。

你应该这样做:

import copy

class Test:
    def __init__(self,a):
        self.a = a

test1 = Test(0)
test2 = copy.deepcopy(test1)

print("Original:")
print("Test 1: " + str(test1.a)) #0
print("Test 2: " + str(test2.a)) #0

print("Modify test 2 to 10")
test2.a = 10
print("Test 1: " + str(test1.a)) #0
print("Test 2: " + str(test2.a)) #10

Original:

Test 1: 0

Test 2: 0

Modify test 2 to 10

Test 1: 0

Test 2: 10

你的第一个问题:

正如@Blckknght 在评论中指出的那样,当您将 class-definition 对象传递给 copy.deepcopy() 时,您 运行 变成了令人惊讶的 deepcopy() 行为/ 古怪,虽然是有意的 - 而不是制作 class-definition 对象的深层副本,deepcopy() 只是 returns 对同一 class-definition 对象的 引用 .

为了验证这一点,

print ("b is:", b)
b_instance = b()
print ("b is Test ?:", (b is Test))

给出:

b is: <class '__main__.Test'>
b is Test ?: True             # deepcopy() hasn't made a copy at all !

以下是 the doc 关于 class-definition 对象的 deepcopy() 的说法:

This module does not copy types like module, method, stack trace, stack frame, file, socket, window, array, or any similar types. It does “copy” functions and classes (shallow and deeply), by returning the original object unchanged; this is compatible with the way these are treated by the pickle module.

所以,当你这样做时

b.a = 1

您仍在修改 class Test 的 class 变量。

你的第二个问题:

当你这样做时

c = type('Test2', (Test,), {'a': 2})

正在创建一个名为Test2的新类型,它有自己的class变量a,并且有Test 作为它的超级class.

现在 Test2.aTest.a 是两个不同的 class 变量,定义在两个不同的 class 中,并且可以相互独立地取值。一个是superclassTest中一个叫a的class变量,另一个是a中的同名class变量a subclass Test2.

这就是为什么c.a会给出2(你初始化它的值),而Test.a会继续给出1