首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >类范围内的动态实例变量

类范围内的动态实例变量
EN

Stack Overflow用户
提问于 2011-04-20 17:34:27
回答 1查看 658关注 0票数 1

我有一个类,它是SQLAlchemy的声明基的后代。我需要编写一个桥对象,它将在声明基和我正在运行的另一个系统之间进行转换,但我希望桥对象不必确切地知道我记录中的列。在这种情况下,我希望有一种方法来列出记录中的所有列,避免不得不在两个只有模糊关联的地方维护属性列表,同时最小化复制。这意味着我可以创建列属性,然后维护一个单独的列名列表,但是同样,复制也是一个因素--如果我以后想改变这个东西的结构,我必须在这两个地方更改它。

在这种情况下,我考虑将列定义放在dict中,然后遍历dict,使用setattr创建每个列定义,如下所示:

代码语言:javascript
运行
复制
    for k,v in self.__column_dict.items():
        setattr(self,k,
                sqlalchemy.Column(v['column_type'],**v.get('opts',{})),
                )

现在,问题是:如果我把这段代码放在类级别上,那么self还没有被定义,并且我得到了一个错误(这是有意义的)。如果我把它放在__init__中,就会定义self,但是SQLAlchemy的声明基会给出一个错误,因为在类定义完成之前,表上没有主键(这很有意义,因为这些属性直到运行时才会被设置)。

所以,所有的人都说,我如何得到我想要的,而不使用eval,或者说,在这里,我只能使用eval?

编辑:我接受了下面的解决方案,但没有百分之百地使用它(尽管它对我得到答案绝对有帮助)。下面是我最后所做的:(请注意,DeclarativeMeta是sqlalchemy.ext.declarative的一部分,与declarative_base相同)

代码语言:javascript
运行
复制
class MyMeta(DeclarativeMeta):
    def __new__(meta, classname, bases, dict_):
        klass = type.__new__(meta, classname, bases, dict_)
        if dict_.has_key('__classinit__'):
            klass.__classinit__ = staticmethod(klass.__classinit__.im_func)
        klass.__classinit__(klass, dict_)
        return klass

然后,在我的派生类中,

代码语言:javascript
运行
复制
class DerivedClass(declarative_base()):
    __tablename__ = 'yaddayadda'
    __metaclass__ = MyMeta

    def __classinit__(klass, dict_):
        klass.__column_dict = <column dict here>

        for k,v in klass.__column_dict.items():
            setattr(klass,k,
                <fancy column stuff>
                )
   ...<rest of class definition>...
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-04-20 21:00:01

这可以通过向declarative_base和该元类提供元类来实现。

代码语言:javascript
运行
复制
from sqlalchemy import Column, Integer
from sqlalchemy.ext.declarative import declarative_base, DeclarativeMeta

class MyMeta(DeclarativeMeta): 

    def __init__(klass, classname, bases, dict_): 

        for k, v in dict_.items():

            if k.endswith('__column_dict'):

                for name, datatype, is_pk in v:

                    setattr(klass, name, Column(name, datatype, primary_key=is_pk))

        return DeclarativeMeta.__init__(klass, classname, bases, dict_)

Base = declarative_base(metaclass=MyMeta)

class Bob(Base):
    __tablename__ = 'bob'
    __column_dict = [('a', Integer, True), ('b', Integer, False)]

bob = Bob()
print bob.a
print bob.b
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5734301

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档