2008-09-04 12 views

cevap

11

İşte bunu yapmak için tek yolu şudur:

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 
+0

Benim çözümüm, 'cls' doğrudan torunları olmayan sınıfları döndürmeyecek. Aşağıdaki quamrana'nın çözümü, atalarının içinde bir yeri olan herhangi bir sınıfı bulacaktır. –

1

Chris Atlee ve zacherates gelen cevapların ne gereklerini yerine getirmek olduğunu önerebilir

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'>)] 
4

foo.py modül Verilen? Ben zacerates cevap bu değişiklik olduğunu düşünüyorum daha iyi:

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 

Bana verilen cevaplar katılmıyorum nedeni ilk verilen sınıfın uzak bir alt sınıfıdır sınıfları üretmez ve ikinci verilmiş içerir olmasıdır sınıf.

20

Quamrana'nın önerisi iyi çalışıyor olsa da, daha fazla pythonic yapmayı önermek istiyorum birkaç olası iyileştirmeler var. Standart kütüphaneden inceleme modülünü kullanmaya güveniyorlar.

  1. Sen inspect.getmembers()
  2. deneme/yakalama kullanarak getattr çağrıyı önleyebilirsiniz olanlar ile inspect.isclass()

kullanılarak önlenebilir, sen eğer tek bir liste anlama Tüm olayı azaltabilir benzeri:

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

Harika çalışıyor, ama yanıtım ayrıca temel sınıf (clazz ile gönderdiğim), herhangi bir fikir döndürür? – fredrik

+0

Fredrik, issubclass (Foo, Foo) isminin tersi. Kolay düzeltme olsa da. – runeh

+2

-1 listesine "ekle" ve "clz değil" ifadesini ekleyin: kod çalışmıyor. dürüst olmak gerekirse: 'isim için cls, inspect.getmembers içinde cls (modül)' – tback

İlgili konular