2009-03-12 6 views
4

は、次のコードPythonのイントロスペクション:オブジェクト属性の「ソートされていない」リストを取得する方法は?

import types 
class A: 
    class D: 
     pass 
    class C: 
     pass 
for d in dir(A): 
    if type(eval('A.'+d)) is types.ClassType: 
     print d 

出力

C 
D 

どのように私はそれがこれらのクラスは、コードで定義された順序で出力するのですか?私。

D 
C 

inspect.getsource(A)を使用して解析する以外に方法はありますか?

+0

なぜこれをやりたいですか? –

+2

djangoのフォームとモデル宣言は、エントリが作成された順番で行おうとします。ただし、属性はクラス宣言とは対照的にインスタンスです。私はクラス宣言が自動テンプレートの生成に役立つように順序付けられているかどうかを調べようとしています。 – molicule

+0

このような奇妙な質問のために、あなたがやろうとしていることをやりたい理由を説明し、djangoタグを追加する方がいいでしょう。 –

答えて

4

inspectモジュールもfindsource機能を持っている(あなたがOrderedMetaに興味を持っているすべてのクラスのメタクラスを設定する必要)です。これは、オブジェクトが定義されているソース行と行番号の組を返します。

>>> import inspect 
>>> import StringIO 
>>> inspect.findsource(StringIO.StringIO)[1] 
41 
>>> 

findsource機能は、実際に検索し、ソースファイルを谷とそれは、クラスオブジェクトを指定された場合に可能性の高い候補者を探します。

メソッドオブジェクト、関数オブジェクト、トレースバックオブジェクト、フレームオブジェクト、またはコードオブジェクトがある場合、(含まれている)コードオブジェクトのco_firstlineno属性を参照するだけです。

1

AFAIK、ノー※はありません。これは、すべてのクラスの属性が辞書に格納されているためです(これは、あなたが分かっているように順序付けられていません)。

*:実際には可能かもしれませんが、デコレータまたはメタクラスハッキングのいずれかが必要です。それらのどちらかに興味がありますか?

5

いいえ、あなたが探している順序でそれらの属性を取得することはできません。 Pythonの属性はdict(read:hashmap)に格納されています。これは挿入順序を認識しません。

また、私は単にあなたのループ内

if type(getattr(A, d)) is types.ClassType: 
    print d 

を言ってはevalの使用を避けるだろう。 A.__dict__

+1

さて、evalの代わりにgetattrを使用するには+1してください。 –

0

私はここでglibをしようとはしていませんが、ソースのアルファベット順にクラスを編成することは可能でしょうか?私は、1つのファイルにたくさんのクラスがあるとき、これはそれ自身の役に立つことができることを知ります。

8

inspectで解析がすでに完了していることに注意してください。inspect.findsourceを見てください。モジュールはクラス定義を検索し、ソースと行番号を返します。その行番号をソートすると(別のモジュールで定義されたクラスを分割する必要があるかもしれません)、正しい順序が与えられます。

ただし、この関数は文書化されていないようで、正規表現を使用して行を検索するだけなので、信頼性が高くない可能性があります。

別の方法として、メタクラスを使用する方法や、暗黙的または明示的にオブジェクトに情報を順序付ける方法があります。たとえば:

import itertools, operator 

next_id = itertools.count().next 

class OrderedMeta(type): 
    def __init__(cls, name, bases, dct): 
     super(OrderedMeta, cls).__init__(name, bases, dct) 
     cls._order = next_id() 

# Set the default metaclass 
__metaclass__ = OrderedMeta 

class A: 
    class D: 
     pass 
    class C: 
     pass 

print sorted([cls for cls in [getattr(A, name) for name in dir(A)] 
      if isinstance(cls, OrderedMeta)], key=operator.attrgetter("_order")) 

は、しかし、これはかなり煩わしい変更が

+0

私はこのアプローチが好きでしたが、inspect.findsourceを使って行って、MizardXの答えを選んだ – molicule

関連する問題