Code Yarns ‍👨‍💻
Tech BlogPersonal Blog

How to discover type hierarchy in Python

📅 2017-Dec-11 ⬩ ✍️ Ashwin Nanjappa ⬩ 🏷️ python, type ⬩ 📚 Archive

Given any type in Python, you can easily discover its ancestor and descendant types. This ease of discovery of the internals of the language is one of my favorite features of Python.

#!/usr/bin/env python3

"""Print hierarchy of types present in Python."""

import argparse
import sys

def is_builtin(t):
    """Check if type is builtin."""
    builtin_s = "__builtin__" if sys.version_info.major <= 2 else "builtins"
    return t.__module__ == builtin_s

def process_a_type(t, level, options):

    # Not a builtin type
    if options.only_builtins and not is_builtin(t):
        return

    # Print type
    s = ""
    if level > 0:
        s += "    " * (level - 1)
        s += "+-- "
    s += t.__name__
    if options.show_module:
        s += " ({})".format(t.__module__)
    print(s)

    # -type- has no subclasses
    if t.__name__ == "type":
        return

    # Recurse through child types
    for st in t.__subclasses__():
        process_a_type(
            st,
            level + 1,
            options,
        )

def get_args():
    ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    ap.add_argument("--only_builtins", default=False, action="store_true", help="Only show builtin types")
    ap.add_argument("--show_module", default=False, action="store_true", help="Show module name beside type")
    ap.add_argument("--import_module", default="", type=str, help="Import this module to get its types")
    args = ap.parse_args()
    return args

def main():
    args = get_args()

    # Import module wanted by user
    if args.import_module:
        __import__(args.import_module)

    # -object- type is root
    process_a_type(
        object,
        0,
        args,
    )

if __name__ == "__main__":
    main()
object
+-- type
+-- dict_values
    +-- odict_values
+-- tuple_iterator
+-- set
+-- fieldnameiterator
+-- frame
+-- dict_keyiterator
+-- PyCapsule
+-- coroutine
+-- bytearray
+-- NoneType
+-- list
+-- dict
+-- getset_descriptor
+-- method-wrapper
+-- method
+-- str_iterator
+-- formatteriterator
+-- str
+-- set_iterator
+-- range_iterator
+-- memoryview
+-- cell
+-- generator
+-- map
+-- list_iterator
+-- stderrprinter
+-- reversed
+-- method_descriptor
+-- code
+-- weakproxy
+-- int
    +-- bool
+-- ellipsis
+-- module
+-- dict_items
    +-- odict_items
+-- bytearray_iterator
+-- Struct
+-- moduledef
+-- filter
+-- staticmethod
+-- tuple
+-- frozenset
+-- managedbuffer
+-- coroutine_wrapper
+-- function
+-- builtin_function_or_method
+-- odict_iterator
+-- float
+-- range
+-- super
+-- dict_keys
    +-- odict_keys
+-- list_reverseiterator
+-- bytes_iterator
+-- member_descriptor
+-- wrapper_descriptor
+-- property
+-- instancemethod
+-- zip
+-- weakref
+-- slice
+-- longrange_iterator
+-- dict_valueiterator
+-- EncodingMap
+-- callable_iterator
+-- mappingproxy
+-- BaseException
    +-- Exception
        +-- TypeError
        +-- StopAsyncIteration
        +-- SyntaxError
            +-- IndentationError
                +-- TabError
        +-- AttributeError
        +-- AssertionError
        +-- StopIteration
        +-- MemoryError
        +-- BufferError
        +-- NameError
            +-- UnboundLocalError
        +-- LookupError
            +-- IndexError
            +-- KeyError
        +-- EOFError
        +-- ImportError
        +-- ValueError
            +-- UnicodeError
                +-- UnicodeEncodeError
                +-- UnicodeDecodeError
                +-- UnicodeTranslateError
        +-- RuntimeError
            +-- RecursionError
            +-- NotImplementedError
        +-- SystemError
        +-- Warning
            +-- UserWarning
            +-- DeprecationWarning
            +-- BytesWarning
            +-- SyntaxWarning
            +-- PendingDeprecationWarning
            +-- FutureWarning
            +-- ResourceWarning
            +-- ImportWarning
            +-- RuntimeWarning
            +-- UnicodeWarning
        +-- ReferenceError
        +-- OSError
            +-- ConnectionError
                +-- BrokenPipeError
                +-- ConnectionAbortedError
                +-- ConnectionRefusedError
                +-- ConnectionResetError
            +-- BlockingIOError
            +-- NotADirectoryError
            +-- PermissionError
            +-- FileExistsError
            +-- TimeoutError
            +-- IsADirectoryError
            +-- InterruptedError
            +-- ProcessLookupError
            +-- FileNotFoundError
            +-- ChildProcessError
        +-- ArithmeticError
            +-- FloatingPointError
            +-- OverflowError
            +-- ZeroDivisionError
    +-- GeneratorExit
    +-- KeyboardInterrupt
    +-- SystemExit
+-- dict_itemiterator
+-- classmethod
+-- NotImplementedType
+-- iterator
+-- bytes
+-- enumerate
+-- classmethod_descriptor
+-- complex
+-- traceback
+-- weakcallableproxy
object
+-- type
+-- weakref
+-- weakcallableproxy
+-- weakproxy
+-- int
    +-- bool
+-- basestring
    +-- str
    +-- unicode
+-- bytearray
+-- list
+-- NoneType
+-- NotImplementedType
+-- traceback
+-- super
+-- xrange
+-- dict
+-- set
+-- slice
+-- staticmethod
+-- complex
+-- float
+-- buffer
+-- long
+-- frozenset
+-- property
+-- memoryview
+-- tuple
+-- enumerate
+-- reversed
+-- code
+-- frame
+-- builtin_function_or_method
+-- instancemethod
+-- function
+-- classobj
+-- dictproxy
+-- generator
+-- getset_descriptor
+-- wrapper_descriptor
+-- instance
+-- ellipsis
+-- member_descriptor
+-- file
+-- PyCapsule
+-- cell
+-- callable-iterator
+-- iterator
+-- EncodingMap
+-- fieldnameiterator
+-- formatteriterator
+-- module
+-- classmethod
+-- dict_keys
+-- dict_items
+-- dict_values
+-- deque_iterator
+-- deque_reverse_iterator
+-- Struct