التكرار على الفئات الفرعية لفئة معينة في وحدة نمطية معينة

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

  •  09-06-2019
  •  | 
  •  

سؤال

في Python، بالنظر إلى الوحدة X والفئة Y، كيف يمكنني تكرار أو إنشاء قائمة بجميع الفئات الفرعية Y الموجودة في الوحدة X؟

هل كانت مفيدة؟

المحلول

إليك طريقة واحدة للقيام بذلك:

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 يعمل بشكل جيد، إلا أن هناك بعض التحسينات المحتملة التي أود أن أقترحها لجعله أكثر لغة بايثونية.يعتمدون على استخدام وحدة الفحص من المكتبة القياسية.

  1. يمكنك تجنب استدعاء getattr باستخدام inspect.getmembers()
  2. يمكن تجنب المحاولة/الالتقاط باستخدام inspect.isclass()

مع هذه، يمكنك تقليل الأمر برمته إلى قائمة واحدة إذا أردت:

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

سبب عدم موافقتي على الإجابات المقدمة هو أن الأولى لا تنتج فئات تمثل فئة فرعية بعيدة عن فئة معينة، والثانية تتضمن فئة معينة.

بالنظر إلى الوحدة 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