私信  •  关注

David Z

David Z 最近创建的主题
David Z 最近回复了

我可以想到两种选择:要么重复呼叫 property 在子类中,

class B(A):
    def f1(self):
        return [1,2]
    test1 = property(f1)

或将属性基于另一个调用 f1 :

class A(object):
    def f1(self):
        return []
    def _f1(self):
        return self.f1()
    test1 = property(_f1)
14 年前
回复了 David Z 创建的主题 » python中的copy和deepcopy帮助

如果我记忆/思考正确,在sqlAlchemy中,通常一次只有一个对象对应于给定的数据库记录。这样做是为了让sqlAlchemy可以使您的python对象与数据库保持同步,反之亦然(好吧,如果没有来自python外部的并发db突变,那就另当别论了)。所以问题是,如果要复制这些映射对象中的一个,最终会得到两个不同的对象,它们对应于同一个数据库记录。如果您更改一个,那么它们将具有不同的值,并且数据库不能同时匹配这两个值。

我认为您可能需要做的是决定是否希望数据库记录反映更改副本属性时所做的更改。如果是这样,那么您根本不应该复制对象,您应该只是重用相同的实例。

另一方面,如果不希望在更新副本时更改原始数据库记录,则可以选择:副本是否应成为数据库中的新行?或者根本不应该映射到数据库记录?在前一种情况下,可以通过创建同一类的新实例并复制值来实现复制操作,这与创建原始对象的方式基本相同。这可能是在 __deepcopy__() sqlAlchemy映射类的方法。在后一种情况下(没有映射),您将需要一个单独的类,该类具有所有相同的字段,但不使用SQLAlchemy进行映射。实际上,让您的sqlAlchemy映射类成为这个未映射类的子类可能更有意义,并且只为子类进行映射。

编辑 :好的,澄清我最后一点的意思:现在你有一个 Student 用来代表学生的课程。我建议你 学生 未映射的常规类:

class Student(object):
    def __init__(self, sid, name, allocated_proj_ref, allocated_rank):
        self.sid = sid
        self.name = name
        self.allocated_project = None
        self.allocated_rank = None

有一个子类,比如 StudentDBRecord ,将映射到数据库。

class StudentDBRecord(Student):
    def __init__(self, student):
        super(StudentDBRecord, self).__init__(student.sid, student.name,
            student.allocated_proj_ref, student.allocated_rank)

# this call remains the same
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)
)

# this changes
mapper(StudentDBRecord, students_table, properties={'proj' : relation(Project)})

现在,您将使用以下实例实现优化算法 学生 ,它是未映射的-例如 学生 对象发生更改,数据库不会发生任何变化。这意味着你可以安全使用 copy deepcopy 根据需要。完成后,您可以更改 学生 实例到 学生数据库记录 实例,比如

students = ...dict with best solution...
student_records = [StudentDBRecord(s) for s in students.itervalues()]
session.commit()

这将创建对应于处于最佳状态的所有学生的映射对象,并将其提交到数据库。

编辑2 :所以这可能不起作用。快速解决方法是复制 学生 构造函数转换为 学生数据库记录 并使 学生数据库记录 延伸 object 相反。也就是说,替换以前的定义 学生数据库记录 用这个:

class StudentDBRecord(object):
    def __init__(self, student):
        self.sid = student.sid
        self.name = student.name
        self.allocated_project = student.allocated_project
        self.allocated_rank = student.allocated_rank

或者如果你想概括一下:

class StudentDBRecord(object):
    def __init__(self, student):
        for attr in dir(student):
            if not attr.startswith('__'):
                setattr(self, attr, getattr(student, attr))

后一个定义将复制 学生 学生数据库记录 .