是否有基于类属性创建__init__函数的快捷方式?

时间:2013-08-09 16:17:26

标签: python class oop sqlalchemy

我正在使用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__?这些是新式的课程。

2 个答案:

答案 0 :(得分: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__

答案 1 :(得分:1)

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

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

如果从该类继承,则所有新类都具有相同的方法,您可以使用super调用它。