4

我想覆盖__deepcopy__给定的 SQLAlchemy 映射类,以便它忽略任何 SQLA 属性,但深度复制属于该类的所有其他内容。

我不是特别熟悉重写任何 Python 的内置对象,但我对我想要什么有所了解。

让我们创建一个User使用 SQLA 映射的非常简单的类。

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.

Questions
如果这些是唯一的,我在定义时如何忽略它__deepcopy__
此外,SQLA 是否有任何属性注入到映射对象中?


(我在上一个问题中问过这个问题(不过,在我选择了主要问题的答案几天后进行了编辑),但我想我错过了那里的火车。为此道歉。)


Edit - Fixed code thanks to zifot's answer

我从 Python 文档中得到的唯一一件事是您需要将 deepcopy with 定义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仍然具有 SQLA 属性...

我愿意提供帮助、建议等。

4

4 回答 4

2

当(深度)复制时,您不应该调用__init__,而是调用__new__.

一个例子:

def __copy__(self):
    cls = self.__class__
    newobject = cls.__new__(cls)
    newobject.__dict__.update(self.__dict__)
    return newobject
于 2016-12-16T12:57:39.453 回答
1

mavnn是对的。例如尝试将您的用户初始化更改为:

def __init__(self, user_id = None, name = None):
        self.user_id = user_id
        self.name = name

至于复制映射的实例,我建议阅读这个线程

于 2010-06-14T12:08:46.657 回答
0

要排除 sqlalchemy 列和映射属性,您可以执行以下操作:

for attr in dir(self):
    if not self._sa_class_manager.mapper.has_property(key):
        ...
于 2010-06-14T23:07:49.127 回答
0

我不是 deepcopy 方面的专家,但从错误看来,您需要一个无参数构造函数才能在self.__class__()没有参数的情况下调用。

于 2010-06-14T11:59:23.463 回答