如何在Python中“重写”deepcopy?
我想要重写一个叫做 __deepcopy__
的方法,用在一个用 SQLAlchemy 映射的类上,这样它就能忽略任何 SQLAlchemy 特有的属性,但能深拷贝类中的其他所有内容。
我对重写 Python 内置对象的知识不太多,但我大致知道我想要什么。
我们先来创建一个非常简单的类 User
,这个类是用 SQLAlchemy 映射的。
class User(object):
def __init__(self, user_id=None, name=None):
self.user_id = user_id
self.name = name
我用 dir()
函数查看了在映射之前和之后,SQLAlchemy 特有的属性有哪些,发现了 _sa_class_manager
和 _sa_instance_state
。
问题
如果这些是唯一的属性,我该如何在定义 __deepcopy__
时忽略它们呢?
另外,SQLAlchemy 是否会在映射的对象中注入其他属性?
(我在之前的问题中问过这个(在我选择了主要问题的答案后几天进行了编辑),但我觉得我错过了机会。对此我表示歉意。)
编辑 - 感谢 zifot 的回答修复了代码
我从 Python 文档中了解到,定义深拷贝时需要把 memo
作为一个额外的参数。经过一点小小的探索,我尝试了这个:
def __deepcopy__(self, memo):
dpcpy = self.__class__()
memo[id(self)] = dpcpy
for attr in dir(self):
if not attr.startswith('_'):
value = getattr(self, attr)
setattr(dpcpy, attr, copy.deepcopy(value, memo))
return dpcpy
然后我创建了一个 User
的实例,如下:
snake = User(913, 'Snake,S.')
之后,我尝试进行了一个 deepcopy
操作,如下:
snake_dc = copy.deepcopy(snake)
...结果 snake_dc
里还是有 SQLAlchemy 的属性...
我非常欢迎任何帮助、建议等。
4 个回答
0
我不是深拷贝方面的专家,但从这个错误来看,似乎你需要一个不带参数的构造函数,这样才能在调用 self.__class__()
时不传任何参数。
2
在进行(深)复制的时候,你不应该调用 __init__
方法,而是应该调用 __new__
方法。
下面是一个例子:
def __copy__(self):
cls = self.__class__
newobject = cls.__new__(cls)
newobject.__dict__.update(self.__dict__)
return newobject