2

我正在使用 sqlalchemy 的 ORM,并且我有一堆Declarative具有类属性的类。例如:

class Example(Declarative):
    id = Column(Integer, primary_key=True)
    datum = Column(String(65))

当然,我的课程比这个例子长得多,我大约有两打。我希望能够在实例化时填充他们的字段,所以__init__每个类都有函数会很好。

天真的方法如下:

    def __init__(self, id, datum):
        self.id = id
        self.datum = datumi

这变得非常乏味。有什么捷径吗?也许我可以利用Example.__dict__?这些是新式课程。

4

2 回答 2

3

您根本不需要创建__init__方法;SQLAlchemy 为您提供了一种开箱即用的方法。

即使您确实必须构建一个,您也可以接受任意关键字参数。这正是 SQLAlchemy 版本所做的:

def _declarative_constructor(self, **kwargs):
    """A simple constructor that allows initialization from kwargs.

    Sets attributes on the constructed instance using the names and
    values in ``kwargs``.

    Only keys that are present as
    attributes of the instance's class are allowed. These could be,
    for example, any mapped columns or relationships.
    """
    cls_ = type(self)
    for k in kwargs:
        if not hasattr(cls_, k):
            raise TypeError(
                "%r is an invalid keyword argument for %s" %
                (k, cls_.__name__))
        setattr(self, k, kwargs[k])

setattr()翻译成散文,此方法在用于设置实例值之前测试您传入的每个关键字是否都是类的属性。

请注意,这使用关键字参数;您无法使用位置参数来执行此操作,因为您的类属性存储在字典中,因此没有设置顺序。如果要使用位置参数,则需要手动创建一个方法,或者在类上__init__定义一个顺序以供(继承)使用:__init__

class Example(Declarative):
    id = Column(Integer, primary_key=True)
    datum = Column(String(65))
    __order__ = ('id', 'datum')

    def __init__(self, *args, **kwargs):
        cls_ = type(self)
        kwargs.update(zip(cls_.__order__, args))
        for k in kwargs:
            if not hasattr(cls_, k):
                raise TypeError(
                    "%r is an invalid keyword argument for %s" %
                    (k, cls_.__name__))
            setattr(self, k, kwargs[k])

在这里,任何位置参数都被合并到类的新属性kwargs中给定的存储字段顺序中。__order__

于 2013-08-09T16:25:59.900 回答
1

您可以定义一个将字典作为输入的类并执行以下操作:

for (k, v) in inital_dict.iteritems():
    setattr(self, k, v)

如果您从该类继承所有新类将具有相同的方法,您可以使用super.

于 2013-08-09T16:25:30.317 回答