指定されたモジュール内の指定されたクラスのサブクラスを反復処理します。

StackOverflow https://stackoverflow.com/questions/44352

  •  09-06-2019
  •  | 
  •  

質問

Python で、モジュール X とクラス Y が与えられた場合、モジュール X に存在する Y のすべてのサブクラスのリストを反復または生成するにはどうすればよいでしょうか?

役に立ちましたか?

解決

その方法の 1 つを次に示します。

import inspect

def get_subclasses(mod, cls):
    """Yield the classes in module ``mod`` that inherit from ``cls``"""
    for name, obj in inspect.getmembers(mod):
        if hasattr(obj, "__bases__") and cls in obj.__bases__:
            yield obj

他のヒント

Quamrana の提案はうまく機能しますが、より Python らしくするために提案したい改善点がいくつかあります。これらは、標準ライブラリの検査モジュールの使用に依存しています。

  1. 次を使用すると、getattr 呼び出しを回避できます。 inspect.getmembers()
  2. トライ/キャッチは次の方法で回避できます。 inspect.isclass()

これらを使用すると、必要に応じて全体を 1 つのリスト内包表記に減らすことができます。

def find_subclasses(module, clazz):
    return [
        cls
            for name, cls in inspect.getmembers(module)
                if inspect.isclass(cls) and issubclass(cls, clazz)
    ]

Chris AtLee と zacherates のどちらの回答も要件を満たしていないと言えますか?zacerates の回答に対するこの変更の方が良いと思います。

def find_subclasses(module, clazz):
    for name in dir(module):
        o = getattr(module, name)
        try:
            if (o != clazz) and issubclass(o, clazz):
                yield name, o
        except TypeError: pass

私が与えられた答えに同意しない理由は、最初の答えは与えられたクラスの遠いサブクラスであるクラスを生成せず、2番目の答えは与えられたクラスを含むからです。

モジュール foo.py を指定すると、

class foo(object): pass
class bar(foo): pass
class baz(foo): pass

class grar(Exception): pass

def find_subclasses(module, clazz):
    for name in dir(module):
        o = getattr(module, name)

        try: 
             if issubclass(o, clazz):
             yield name, o
        except TypeError: pass

>>> import foo
>>> list(foo.find_subclasses(foo, foo.foo))
[('bar', <class 'foo.bar'>), ('baz', <class 'foo.baz'>), ('foo', <class 'foo.foo'>)]
>>> list(foo.find_subclasses(foo, object))
[('bar', <class 'foo.bar'>), ('baz', <class 'foo.baz'>), ('foo', <class 'foo.foo'>), ('grar', <class 'foo.grar'>)]
>>> list(foo.find_subclasses(foo, Exception))
[('grar', <class 'foo.grar'>)]
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top