4.5. Debugging Introspection

  • Introspection is the ability to determine the type of an object at runtime

  • Everything in Python is an object and we can examine those objects

  • Python ships with a few built-in functions and modules to help us

4.5.1. Introspecting Types

4.5.2. id()

id('hello')
# 4596416368
id('hello')
# 4592969392
name = 'hello'

id(name)
# 4596353264
id(name)
# 4596353264
id('hello')
# 4466061520
id(str)
# 4306722176

4.5.3. type()

type('')                            # <type 'str'>
type(str)                           # <class 'type'>

type([])                            # <type 'list'>
type(list)                          # <class 'type'>

type({})                            # <type 'dict'>
type(dict)                          # <type 'type'>

type(3)                             # <type 'int'>
type(int)                           # <class 'type'>

4.5.4. isinstance()

my_data = {}
isinstance(my_data, (set, dict))    # True
isinstance(my_data, dict)           # True
isinstance(my_data, set)            # False
my_data = {1}
isinstance(my_data, dict)           # False
isinstance(my_data, set)            # True
my_data = {1: 1}
isinstance(my_data, dict)           # True
isinstance(my_data, set)            # False

4.5.5. issubclass()

class Cosmonaut:
    pass

class GieroyCCCP(Cosmonaut):
    pass


issubclass(Cosmonaut, Cosmonaut)     # True
issubclass(Cosmonaut, GieroyCCCP)    # False
issubclass(GieroyCCCP, GieroyCCCP)   # True
issubclass(GieroyCCCP, Cosmonaut)    # True

4.5.6. callable()

class Car:
    def setName(self, name):
        self.name = name

def fun():
    pass

c = Car()

callable(fun)                       # True
callable(c.setName)                 # True
callable([])                        # False
callable(1)                         # False

4.5.7. Introspecting Objects

4.5.8. dir()

  • Returns a list of attributes and methods belonging to an object

class Server:
    """Connects to the server"""
    _connection = None

    def __init__(self, host, port):
        """Initializes object"""
        self.host = host
        self.port = port

    def login():
        """logs-in to the server"""

connection = Server(host='example.com', port=1337)

result = dir(connection)
print(result)
# ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__',
#  '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__',
# '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
# '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__',
# '_connection', 'host', 'login', 'port']

4.5.9. object.__dict__

  • Returns dynamic fields of an object

class Server:
    """Connects to the server"""
    _connection = None

    def __init__(self, host, port):
        """Initializes object"""
        self.host = host
        self.port = port

    def login():
        """logs-in to the server"""

connection = Server(host='example.com', port=1337)

connection.__dict__
# {'host': '127.0.0.1', 'port': 1337}

4.5.10. vars()

class Server:
    """Connects to the server"""
    _connection = None

    def __init__(self, host, port):
        """Initializes object"""
        self.host = host
        self.port = port

    def login():
        """logs-in to the server"""

connection = Server(host='example.com', port=1337)

vars(Server)
# {
#    '__module__': '__main__',
#    '__doc__': 'Connects to the server',
#    '_connection': None,
#    '__init__': <function Server.__init__ at 0x111f77488>,
#    'login': <function Server.login at 0x111f77268>,
#    '__dict__': <attribute '__dict__' of 'Server' objects>,
#    '__weakref__': <attribute '__weakref__' of 'Server' objects>
# }

4.5.11. hasattr(), getattr(), setattr()

class User:
    def __init__(self, **kwargs):
        for name, value in kwargs.items():
            setattr(self, name, value)

    def __str__(self):
        if hasattr(self, 'firstname'):
            firstname = getattr(self, 'firstname')

        lastname = getattr(self, 'lastname', 'n/a')
        return f'Hello {firstname} {lastname}'


 alice = User(firstname='Alice', lastname='Apricot')

 print(alice)
 # Hello Alice

4.5.12. inspect module

The inspect module also provides several useful functions to get information about live objects. For example you can check the members of an object by running:

import inspect

inspect.getmembers(str)
# [('__add__', <slot wrapper '__add__' of ... ...

4.5.13. Introspecting Docstrings

4.5.14. help()

class Server:
    """Connects to the server"""
    _connection = None

    def __init__(self, host, port):
        """Initializes object"""
        self.host = host
        self.port = port

    def login():
        """logs-in to the server"""

connection = Server(host='example.com', port=1337)

help(connection)
# Help on Server in module __main__ object:
#
# class Server(builtins.object)
#  |  Server(host, port)
#  |
#  |  Connects to the server
#  |
#  |  Methods defined here:
#  |
#  |  __init__(self, host, port)
#  |      Initializes object
#  |
#  |  login()
#  |      logs-in to the server
#  |
#  |  ----------------------------------------------------------------------
#  |  Data descriptors defined here:
#  |
#  |  __dict__
#  |      dictionary for instance variables (if defined)
#  |
#  |  __weakref__
#  |      list of weak references to the object (if defined)

4.5.15. object.__doc__

class Server:
    """Connects to the server"""
    _connection = None

    def __init__(self, host, port):
        """Initializes object"""
        self.host = host
        self.port = port

    def login():
        """logs-in to the server"""

connection = Server(host='example.com', port=1337)

connection.login.__doc__
# 'logs-in to the server'

4.5.16. Examples

import settings
from django.db import models

for app in settings.INSTALLED_APPS:
    models_name = app + ".models"

    try:
        models_module = __import__(models_name, fromlist=["models"])
        attributes = dir(models_module)

        for attr in attributes:
            try:
                attrib = models_module.__getattribute__(attr)
                if issubclass(attrib, models.Model) and attrib.__module__== models_name:
                print(f'{models_name}.{attr}')
            except TypeError, e:
                pass
    except ImportError, e:
        pass
from django.contrib import admin
from . import models
import inspect

for name, obj in inspect.getmembers(models):
    if inspect.isclass(obj):
        admin.site.register(getattr(models, name))