クラス名を指定してそのクラスのサブクラスをすべて見つけるにはどうすればいいですか? 質問する

クラス名を指定してそのクラスのサブクラスをすべて見つけるにはどうすればいいですか? 質問する

Python の基本クラスから継承されたすべてのクラスを取得するための実用的なアプローチが必要です。

ベストアンサー1

新しいスタイルのクラス (つまりobject、Python 3 のデフォルトである からサブクラス化されたクラス)には__subclasses__、サブクラスを返す メソッドがあります。

class Foo(object): pass
class Bar(Foo): pass
class Baz(Foo): pass
class Bing(Bar): pass

サブクラスの名前は次のとおりです。

print([cls.__name__ for cls in Foo.__subclasses__()])
# ['Bar', 'Baz']

サブクラス自体は次のとおりです。

print(Foo.__subclasses__())
# [<class '__main__.Bar'>, <class '__main__.Baz'>]

サブクラスが実際にFooベースとしてリストされていることの確認:

for cls in Foo.__subclasses__():
    print(cls.__base__)
# <class '__main__.Foo'>
# <class '__main__.Foo'>

サブサブクラスが必要な場合は、再帰する必要があることに注意してください。

def all_subclasses(cls):
    return set(cls.__subclasses__()).union(
        [s for c in cls.__subclasses__() for s in all_subclasses(c)])

print(all_subclasses(Foo))
# {<class '__main__.Bar'>, <class '__main__.Baz'>, <class '__main__.Bing'>}

サブクラスのクラス定義がまだ実行されていない場合、たとえば、サブクラスのモジュールがまだインポートされていない場合、そのサブクラスはまだ存在せず、__subclasses__見つからないことに注意してください。


「名前を指定して」とおっしゃいましたね。Python クラスはファーストクラス オブジェクトなので、クラスの代わりにクラス名の文字列を使用する必要はありません。クラスを直接使用することもできますし、おそらくそうすべきでしょう。

クラス名を表す文字列があり、そのクラスのサブクラスを検索する場合は、2 つの手順があります。まず、クラス名を指定してクラスを検索し、次に__subclasses__上記を使用してサブクラスを検索します。

名前からクラスを見つける方法は、どこで見つけるかによって異なります。クラスを見つけようとしているコードと同じモジュールで見つける場合は、

cls = globals()[name]

役に立つだろう、あるいは地元でそれを見つけることを期待しているという可能性は低いが、

cls = locals()[name]

クラスがどのモジュールにもある可能性がある場合は、名前文字列に完全修飾名 ('pkg.module.Foo'ではなく のような名前) を含める必要があります'Foo'。 を使用してimportlibクラスのモジュールをロードし、対応する属性を取得します。

import importlib
modname, _, clsname = name.rpartition('.')
mod = importlib.import_module(modname)
cls = getattr(mod, clsname)

ただし、クラスを見つけるcls.__subclasses__()と、そのサブクラスのリストが返されます。

おすすめ記事