【发布时间】:2010-06-06 06:00:05
【问题描述】:
我想我试图在my previous question 中要求太多,所以对此表示歉意。这次让我尽可能简单地说明我的情况。
基本上,我有一堆引用我的对象的字典,而这些字典又使用 SQLAlchemy 进行映射。我一切都好。但是,我想对这些词典的内容进行迭代更改。问题是这样做会改变它们引用的对象——并且使用 copy.copy() 没有好处,因为它只复制字典中包含的引用。因此,即使复制了某些内容,当我尝试说print 字典的内容时,我也只会获得该对象的最新更新值。
这就是为什么我想使用 copy.deepcopy() 但它不适用于 SQLAlchemy。现在我处于两难境地,因为我需要在进行上述迭代更改之前复制对象的某些属性。
总之,我需要同时使用 SQLAlchemy 和,确保在进行更改时我可以拥有我的对象属性的副本,这样我就不会更改引用的对象本身。
有什么建议、帮助、建议等吗?
Edit:添加了一些代码。
class Student(object):
def __init__(self, sid, name, allocated_proj_ref, allocated_rank):
self.sid = sid
self.name = name
self.allocated_proj_ref = None
self.allocated_rank = None
students_table = Table('studs', metadata,
Column('sid', Integer, primary_key=True),
Column('name', String),
Column('allocated_proj_ref', Integer, ForeignKey('projs.proj_id')),
Column('allocated_rank', Integer)
)
mapper(Student, students_table, properties={'proj' : relation(Project)})
students = {}
students[sid] = Student(sid, name, allocated_project, allocated_rank)
因此,我将要更改的属性是 allocated_proj_ref 和 allocated_rank 属性。 students_table 使用唯一的学生 ID (sid) 键入。
Question
我想保留我在上面更改的属性——我的意思是,这基本上就是我决定使用 SQLA 的原因。但是,映射的对象会发生变化,不建议这样做。因此,如果我对 doppelgänger、unmapped 对象进行更改...我可以接受这些更改并更新 mapped 对象的字段/表吗?
从某种意义上说,我正在关注 David 的 secondary solution,在那里我创建了另一个未映射的 Class 版本。
我尝试使用下面提到的StudentDBRecord 解决方案,但出现错误!
File "Main.py", line 25, in <module>
prefsTableFile = 'Database/prefs-table.txt')
File "/XXXX/DataReader.py", line 158, in readData
readProjectsFile(projectsFile)
File "/XXXX/DataReader.py", line 66, in readProjectsFile
supervisors[ee_id] = Supervisor(ee_id, name, original_quota, loading_limit)
File "<string>", line 4, in __init__
raise exc.UnmappedClassError(class_)
sqlalchemy.orm.exc.UnmappedClassError: Class 'ProjectParties.Student' is not mapped
这是否意味着Student 必须被映射?
Health warning!
有人在这里指出了一个非常好的附加问题。看,即使我在非映射对象上调用copy.deepcopy(),在这种情况下,假设它是我在上面定义的学生字典,deepcopy 会复制所有内容。我的allocated_proj_ref 实际上是一个Project 对象,我有一个对应的projects 字典。
所以我对students 和projects 都进行了深度复制——我是——他说我会遇到students 的allocated_proj_ref 属性与@987654343 中的实例匹配存在问题的情况@字典。
因此,我认为我必须重新定义/覆盖(这就是所谓的不是吗?)deepcopy 在每个类中使用 def __deecopy__(self, memo): 或类似的东西?
我想覆盖 __deepcopy__ 以便它忽略所有 SQLA 内容(它们是 <class 'sqlalchemy.util.symbol'> 和 <class 'sqlalchemy.orm.state.InstanceState'>),但复制属于映射类的所有其他内容。
有什么建议吗?
【问题讨论】:
-
修改映射对象时,是保留原始版本还是修改后的版本?
-
@Winston:要么保留原件,要么保留特定的更改版本(
best- 查看编辑)。我已经看到了后者的问题,因为best并没有保持静止,因为我正在更新对象本身。叹息。 -
响应您的编辑:您为什么要使用数据库来执行此操作?将
Student作为常规 Python 类,并仅在找到全局最优值之后将其存储在数据库(或文件)中会更有意义。 -
@Az: 是的,如果您要将信息存储在数据库中,您确实需要使用 SQLA 映射 something(或者当然您可以使用较低的级 DB 接口)。我的建议是你只写一次数据库,最后当你有最终的最佳解决方案时。将 SQLAlchemy 配置为在优化运行时忽略对
Student实例的任何更改,或者使用常规未映射版本的Student进行算法,并且仅在完成后将数据传输到映射的Student对象中。 -
@Az:最后一点,没有理由必须是
__init__(self, student)而不是__init__(self, sid, ...)。无论哪种方式都会奏效。但是由于您只会将StudentDBRecord构造为现有Student的副本,因此将Student传递给构造函数是有意义的。
标签: python copy sqlalchemy