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