Pythonイントロスペクション:オブジェクト属性の「未分類」リストを取得する方法は?
-
11-07-2019 - |
質問
次のコード
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)を使用して解析する以外の方法はありますか?
解決
inspect
モジュールには、 findsource
関数もあります。オブジェクトが定義されているソース行と行番号のタプルを返します。
>>> import inspect
>>> import StringIO
>>> inspect.findsource(StringIO.StringIO)[1]
41
>>>
findsource
関数は、実際にソースファイルを検索し、クラスオブジェクトが与えられている場合に候補を探します。
メソッド、関数、トレースバック、フレーム、またはコードオブジェクトを指定すると、(含まれている)コードオブジェクトの co_firstlineno
属性を単純に参照します。
他のヒント
検査ではすでに解析が行われていることに注意してください- 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"))
ただし、これはかなり面倒な変更です(OrderedMetaに関心のあるクラスのメタクラスを設定する必要があります)
いいえ、探している順序でこれらの属性を取得することはできません。 Python属性は、挿入順序を認識しない辞書(ハッシュマップ)に保存されます。
また、単に言うことでevalの使用を避けます
if type(getattr(A, d)) is types.ClassType:
print d
ループ内で。 A .__ dict __
わかりません、ありません-ありません*。これは、クラスのすべての属性がディクショナリに格納されているためです(ご存じのとおり、順序付けされていません)。
*:実際には可能かもしれませんが、デコレータまたはメタクラスのハッキングが必要になります。どちらか興味がありますか?
ここではglibになろうとはしていませんが、ソースのクラスをアルファベット順に整理することは可能でしょうか? 1つのファイルに多くのクラスがある場合、これはそれ自体で役立つことがあります。