2012-01-21 2 views
4

私はsetup_all()と呼んだとき、私がモデルで宣言したすべてのエンティティクラスをelixir \ sqlalchemyがどのように知っているのですか?私は、私の小さなプロジェクトでこのような機能が必要ですが、私は手がかりがありません。私はエリクシルのsetup_all()を通してsteptraceしようとしましたが、すべてのエンティティクラスのコレクションを "グローバル"リスト(またはdictですか?)で保持していましたが、リストがいっぱいになった瞬間を捕まえられません。何か案は?特定の基本クラスの子孫であるすべてのクラス宣言を反復処理する方法はありますか?

答えて

4

SQLALchemyやelixirを全く使用していない主な質問に答える - はい、Pythonでも可能です。

標準ライブラリのガベージコープレクタ(gc)モジュールには、与えられたオブジェクト、インタープリタワイドへの参照をすべて取得できるようにする関数呼び出しがあります。クラスは、継承されたクラスの__mro__属性で常に参照されます。

ので、次の関数は、与えられたクラスを継承するすべてのクラス取得できます。クラスの定義について

import gc 
def find_subclasses(cls): 
    all_refs = gc.get_referrers(cls) 
    results = [] 
    for obj in all_refs: 
     # __mro__ attributes are tuples 
     # and if a tuple is found here, the given class is one of its members 
     if (isinstance(obj, tuple) and 
      # check if the found tuple is the __mro__ attribute of a class 
      getattr(obj[0], "__mro__", None) is obj): 
      results.append(obj[0]) 
    return results 
+0

素晴らしい!ありがとう、それは完全に動作します! – AlexVhr

9

を、これは簡単です(なしインポート)

def find_subclasses(cls): 
    results = [] 
    for sc in cls.__subclasses__(): 
     results.append(sc) 
    return results 

私はわかりませんあなたがこれを望んでいれば、またはオブジェクト。オブジェクトが必要な場合:

import gc 

def find_subclasses(cls): 
    results = [] 
    for sc in cls.__subclasses__(): 
     for obj in gc.get_objects(): 
      if isinstance(obj, sc): 
       results.append(obj) 
    return results 
+0

はい、インスタンスではなく定義が必要です。ありがとうございました!ショートバージョンルール。 – AlexVhr

+0

どうやら、__subclasses__は新しいスタイルクラスでのみ利用可能であり、呼び出し可能なので、少なくとも2.7.xでは 'cls .__ subclasses __()'となるはずです。 – AlexVhr

+3

@AlexVhrあなたは本当に古い - スタイルクラスはもはや。 – elijaheac

関連する問題