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

Python 类范围内的动态实例变量,python,sqlalchemy,metaclass,setattr,Python,Sqlalchemy,Metaclass,Setattr,我有一个类,它是SQLAlchemy声明性基的后代。我需要编写一个bridge对象,它将在声明性基和我正在运行的另一个系统之间进行转换,但我希望bridge对象不必确切地知道我的记录中有哪些列。在这种情况下,我希望有一种方法列出记录中的所有列,避免在两个仅模糊相关的位置维护属性列表,同时尽量减少复制。这意味着我可以创建列属性,然后维护一个单独的列名列表,但同样,复制是一个因素——如果我想在以后更改它的结构,我必须在两个地方都更改它 在这种情况下,我考虑将列定义粘贴到dict中,然后在dict上迭

我有一个类,它是SQLAlchemy声明性基的后代。我需要编写一个bridge对象,它将在声明性基和我正在运行的另一个系统之间进行转换,但我希望bridge对象不必确切地知道我的记录中有哪些列。在这种情况下,我希望有一种方法列出记录中的所有列,避免在两个仅模糊相关的位置维护属性列表,同时尽量减少复制。这意味着我可以创建列属性,然后维护一个单独的列名列表,但同样,复制是一个因素——如果我想在以后更改它的结构,我必须在两个地方都更改它

在这种情况下,我考虑将列定义粘贴到dict中,然后在dict上迭代以使用setattr创建每个列定义,如下所示:

    for k,v in self.__column_dict.items():
        setattr(self,k,
                sqlalchemy.Column(v['column_type'],**v.get('opts',{})),
                )
现在,麻烦来了:如果我把这段代码放在类级别上,self还没有定义,我会得到一个错误(这是有道理的)。如果我在
\uuuuu init\uuuuuu
中坚持这一点,则会定义self,但SQLAlchemy的声明性基会给出一个错误,因为在定义完类时表上没有主键(这很有意义,因为这些属性在运行时才会设置)

那么,我要说的是,在不使用eval的情况下如何得到我想要的,或者使用eval是我唯一的选择吗


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

然后,在我的派生类中

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>...
class-DerivedClass(声明性_base()):
__tablename_uuu='yaddayada'
__元类\我的元
定义分类(klass,dict):
klass.\uuuu列\u dict=
对于klass中的k,v.\u列\u dict.items():
setattr(克拉斯,k,
)
......

这可以通过向声明性基础提供元类来实现 在那个元类中

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

这可以通过向声明性_库提供元类来实现 在那个元类中

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

非常感谢你。可以肯定的是,我是否也应该在最后打电话给super,以便将来进行校对?例如,返回super(RecordMeta,klass)。\uuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。它似乎将搜索列_dict绑定到RecordMeta,我如何告诉它实际查找的位置?抱歉,这是我提供的一个草率的示例。添加了一个新的完整的。谢谢,非常漂亮,虽然在属性名上使用“endswith”会让人觉得模棱两可,但这似乎很可怕。非常感谢。可以肯定的是,我是否也应该在最后打电话给super,以便将来进行校对?例如,返回super(RecordMeta,klass)。\uuuu init\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。它似乎将搜索列_dict绑定到RecordMeta,我如何告诉它实际查找的位置?抱歉,这是我提供的一个草率的示例。添加了一个新的完整的。谢谢,非常漂亮,尽管在属性名上使用“endswith”会让人觉得模棱两可。