我有一個類是SQLAlchemy的聲明基的後代。我需要編寫一個橋接對象,它將在聲明性基礎和我正在運行的另一個系統之間進行轉換,但是我希望橋對象不必確切地知道我的記錄中有哪些列。既然如此,我想要一種方法來列出記錄中的所有列,以免在兩個模糊相關的地方維護一個屬性列表,並在此期間儘量減少複製。這意味着我可以創建列屬性,然後維護一個單獨的列名稱列表,但同樣,複製是一個因素 - 如果以後我想改變這個東西的結構,我不得不在兩個地方改變它。類範圍內的動態實例變量
既然如此,我想過在一個字典粘列定義,然後遍歷字典來創建SETATTR每列的定義,像這樣:
for k,v in self.__column_dict.items():
setattr(self,k,
sqlalchemy.Column(v['column_type'],**v.get('opts',{})),
)
現在,這裏的難題是:如果我在類級別上粘住這段代碼,self還沒有定義,並且我得到一個錯誤(這是有道理的)。如果我堅持這一點在__init__
,自定義,但SQLAlchemy的聲明性基地給出了一個錯誤,因爲在類定義完成之後,表上沒有主鍵(這是有道理的,因爲這些屬性將不會被設置,直到運行)。
所以,所有的說法,我怎麼得到我想要的而不使用eval,或者使用eval我唯一的選擇,在這裏?
編輯:我接受了下面的解決方案,但沒有使用它100%(雖然它是絕對有助於讓我的答案)。下面是我落得這樣做: (注意,DeclarativeMeta是sqlalchemy.ext.declarative的一部分,同一個包declarative_base)
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
然後,在我的派生類,
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>...
非常感謝。可以肯定的是,我是否還應該最後稱之爲超級,以便將來打樣?例如,return super(RecordMeta,klass).__ init __(classname,bases,dict_)? – 2011-04-21 12:46:52
回想起來,當我實現這個時,我得到「類型對象'MyDerivedObject'沒有屬性'_MyMeta__column_dict'。它似乎是將Record_dict的column_dict搜索綁定在一起,我如何告訴它實際看起來在哪裏? – 2011-04-21 13:04:44
對不起,這是我提供的一個馬虎的例子。增加了一個新的完整的。 – GHZ 2011-04-26 09:41:35