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.
Yep,
class A(object):
pass
class B(A):
pass
class C(B):
pass
print(type.mro(C))
[, , , ]
Raf ! WordPress à vidé ma liste ^^
@herison : il me semble que Sam propose l’inverse :
trouver toutes les classes qui m’ont comme ancêtre
type.mro() ou C.__mro__ propose la liste des ancêtres
Raf ! Quel con ! ça fait l’inverse
Un mutable en valeur par défaut c’est un coup à faire une connerie non ?
Sauf qu’un tuple c’est pas mutable ! Et comme il est vide sa valeur booleenne est False. Moi j’aurais mis None pour plus de clarté mais ça ne change pas le programme.