PROJET AUTOBLOG


Sam & Max: Python, Django, Git et du cul

Site original : Sam & Max: Python, Django, Git et du cul

⇐ retour index

Mise à jour

Mise à jour de la base de données, veuillez patienter...

Mais qui donc hérite de ma classe ?

vendredi 20 juin 2014 à 15:39

Pas une question que l’on se pose souvent, à moins d’avoir une lib qui expose une classe avec beaucoup d’introspection.

Ceci dit pour la culture G, je me suis dit que ça pourrait intéresser quelques geeks de savoir comment lister les enfants d’une classe, récursivement.

def subclasses(cls, _found=()):
    """ Retourne toutes les classes héritant d'une classe """
 
    # On check que la classe est hérite bien de "object".
    # Utile uniquement pour un code 2.x qui utiliserait
    # des old style classes, qui n'ont pas "__subclasses__".
    if not isinstance(cls, type):
      raise TypeError('subclasses works only with new-style classes'
                            ', not %s' % cls)
 
    # On va stocker les classes rencontrées dans un set
    # pour éviter les doublons car on peut tomber sur
    # un héritage en forme de diamant.
    _found = _found or set()
 
    try:
      subs = cls.__subclasses__()
    except TypeError:  # Erreur levée si cls == type, petits vicieux
      subs = cls.__subclasses__(cls)
 
    for sub in subs:
        if sub not in _found:
            _found.add(sub)
            # Un appel récursif comme on les aimes
            subclasses(sub, _found)
 
    return _found

Pas très compliqué, donc, si on connait les piègeounets : ça ne marche pas sur les old syle classes, et il y a un traitement spécial pour type. Celà dit, qui utilise encore des old styles classes ? Et franchement lister les héritiers de type, à par pour satisfaire sa curiosité…

Aller, juste pour le fun, sur un virtualenv vierge:

for x in subclasses(object):
    print x
## <type 'callable-iterator'>
## <class '_abcoll.Sized'>
## <type 'exceptions.EOFError'>
## <class '_abcoll.Mapping'>
## <type 'exceptions.UnicodeWarning'>
## <type 'exceptions.IOError'>
## <type 'memoryview'>
## <type 'code'>
## <type 'exceptions.ImportWarning'>
## <type 'sys.flags'>
## <type 'iterator'>
## <class 'warnings.catch_warnings'>
## <type 'exceptions.Warning'>
## <type 'exceptions.EnvironmentError'>
## <type 'dict'>
## <class 'encodings.utf_8.IncrementalEncoder'>
## <type 'weakproxy'>
## <class '_abcoll.Iterator'>
## <type 'sys.version_info'>
## <type 'posix.stat_result'>
## <type 'frozenset'>
## <class 'codecs.CodecInfo'>
## <class 'zipimport.ZipImportError'>
## <type 'exceptions.StopIteration'>
## <type 'exceptions.ImportError'>
## <class 'site._Printer'>
## <type 'weakref'>
## <class '_abcoll.Sequence'>
## <type 'property'>
## <class 'encodings.utf_8.IncrementalDecoder'>
## <type 'imp.NullImporter'>
## <type 'exceptions.TypeError'>
## <type 'bytearray'>
## <type 'int'>
## <type 'exceptions.UnicodeTranslateError'>
## <type 'instance'>
## <type 'exceptions.BaseException'>
## <type 'exceptions.SyntaxWarning'>
## <type 'file'>
## <class '_abcoll.MappingView'>
## <class '_weakrefset._IterationGuard'>
## <type 'exceptions.UnicodeDecodeError'>
## <type 'classobj'>
## <type 'exceptions.UnicodeError'>
## <class 'abc.abstractproperty'>
## <type 'exceptions.DeprecationWarning'>
## <type 'complex'>
## <type 'set'>
## <type 'buffer'>
## <type 'generator'>
## <type 'exceptions.Exception'>
## <class 'codecs.IncrementalDecoder'>
## <type 'exceptions.UserWarning'>
## <type 'staticmethod'>
## <type 'exceptions.UnicodeEncodeError'>
## <class 'encodings.CodecRegistryError'>
## <class '_abcoll.MutableSequence'>
## <class '_abcoll.KeysView'>
## <type 'cell'>
## <type 'exceptions.StandardError'>
## <type 'enumerate'>
## <type 'exceptions.KeyboardInterrupt'>
## <type 'exceptions.BufferError'>
## <class 'warnings.WarningMessage'>
## <type 'EncodingMap'>
## <class 'codecs.BufferedIncrementalDecoder'>
## <type 'exceptions.ValueError'>
## <class '_abcoll.Set'>
## <type 'exceptions.MemoryError'>
## <type 'exceptions.SystemExit'>
## <type 'reversed'>
## <class '_abcoll.Hashable'>
## <type 'bool'>
## <type 'classmethod'>
## <type 'exceptions.ReferenceError'>
## <type 'exceptions.GeneratorExit'>
## <class '_abcoll.Container'>
## <class '_abcoll.ItemsView'>
## <type 'xrange'>
## <type 'exceptions.PendingDeprecationWarning'>
## <type 'basestring'>
## <type 'exceptions.SystemError'>
## <type 'exceptions.ZeroDivisionError'>
## <class 'site.Quitter'>
## <type 'long'>
## <type 'NotImplementedType'>
## <type 'super'>
## <type 'fieldnameiterator'>
## <class '_abcoll.Callable'>
## <class '_abcoll.MutableSet'>
## <type 'exceptions.ArithmeticError'>
## <class 'abc.ABCMeta'>
## <type 'exceptions.OverflowError'>
## <type 'exceptions.FutureWarning'>
## <type 'sys.float_info'>
## <type 'formatteriterator'>
## <type 'type'>
## <type 'exceptions.AssertionError'>
## <type 'traceback'>
## <type 'exceptions.FloatingPointError'>
## <type 'function'>
## <type 'instancemethod'>
## <type 'sys.long_info'>
## <type 'builtin_function_or_method'>
## <class 'signal.ItimerError'>
## <class 'site._Helper'>
## <type 'exceptions.LookupError'>
## <type 'wrapper_descriptor'>
## <type 'exceptions.KeyError'>
## <class '_abcoll.ValuesView'>
## <type 'slice'>
## <class '_weakrefset.WeakSet'>
## <type 'list'>
## <type 'exceptions.IndexError'>
## <type 'getset_descriptor'>
## <type 'posix.statvfs_result'>
## <type 'exceptions.SyntaxError'>
## <type 'frame'>
## <class 'codecs.BufferedIncrementalEncoder'>
## <type 'PyCapsule'>
## <type 'exceptions.IndentationError'>
## <type 'NoneType'>
## <type 'zipimport.zipimporter'>
## <type 'member_descriptor'>
## <type 'exceptions.AttributeError'>
## <type 'ellipsis'>
## <type 'exceptions.UnboundLocalError'>
## <type 'unicode'>
## <class '_abcoll.Iterable'>
## <type 'exceptions.TabError'>
## <type 'exceptions.NameError'>
## <type 'tuple'>
## <class 'warnings._OptionError'>
## <type 'exceptions.NotImplementedError'>
## <type 'exceptions.RuntimeWarning'>
## <type 'str'>
## <class '_abcoll.MutableMapping'>
## <type 'exceptions.BytesWarning'>
## <type 'module'>
## <type 'exceptions.RuntimeError'>
## <class 'codecs.IncrementalEncoder'>
## <type 'float'>
## <type 'exceptions.OSError'>
## <type 'dictproxy'>
## <type 'weakcallableproxy'>

Putain, ça c’est du remplissage ! 20minutes serait fier de moi.

flattr this!