考虑以下代码片段(希望有足够清晰的注释):
from copy import deepcopy
# Needed to be able to set Container __class__.__bases__ to some custom value
class T:
pass
class Container(T):
def __init__(self, x):
self.x = x
class Consolidate:
"Class preventing setting of items and attributes"
def __setattr__(self, key, value):
raise TypeError("Cannot modify %s of object" % key)
def __setitem__(self, key, value):
raise TypeError("Cannot modify %s of object" % key)
def consolidate(obj):
"""
Don't allow further unintentional modification to the object
"""
obj.__class__.__bases__ = obj.__class__.__bases__ + (Consolidate,)
state = Container(1)
# deepcopy last item of the state list
theState = deepcopy(state)
# Prevent modifications of the original state
consolidate(state)
# Print some value for the following question
print("bases of theState? %s" % str(theState.__class__.__bases__))
print("ids of the objects: %d %d" % (id(theState), id(state)))
我得到输出:
bases of theState? (<class '__main__.T'>, <class '__main__.Consolidate'>)
ids of the objects: 140148079864408 140148079838488
我想知道为什么Consolidate类也是State的基础,因为我认为通过深度复制,我只会将其添加到状态列表的最后一个对象中。
我如何达到这样的目标? (防止在对一个对象进行深度复制之后修改其属性,而又不影响复制的对象吗?)
答案 0 :(得分:0)
您更改了类,该类在所有实例之间都是共享。复制会复制实例的状态,而不是类的层次结构,因为类不会被视为状态,因此假定它们保持稳定。
创建一个 second class 并替换您要合并的实例的类,而不是更改该类。复制后,只需将新类分配给__class__
属性即可。
您可以使用type()
function的3参数版本从旧的类创建一个新的类。这也消除了您的T
基类的需要:
class Container:
def __init__(self, x):
self.x = x
class Consolidate:
"Class preventing setting of items and attributes"
def __setattr__(self, key, value):
raise TypeError("Cannot modify %s of object" % key)
def __setitem__(self, key, value):
raise TypeError("Cannot modify %s of object" % key)
def consolidate(obj):
# generate a new class object that adds `Consolidated` to the hierarchy.
cls = type(obj)
consolidated_class = type(cls.__name__ + 'Consolidated', (Consolidate, cls), {})
obj.__class__ = consolidated_class