10. 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

10.1. Introspecting Types

10.1.1. type()

type('')                            # <type 'str'>
type([])                            # <type 'list'>
type({})                            # <type 'dict'>
type(dict)                          # <type 'type'>
type(3)                             # <type 'int'>

10.1.2. id()

id(int)                             # 4306722176
id(int)                             # 4306722176
id('Jose Jimenez')                  # 4596416368
id('Jose Jimenez')                  # 4592969392
name = 'Jose Jimenez'
id(name)                            # 4596353264
id(name)                            # 4596353264

10.1.3. 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

10.1.4. issubclass()

class Cosmonaut:
    pass

class GieroyCCCP(Cosmonaut):
    pass


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

10.1.5. callable()

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

def fun():
    pass

c = Car()

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

10.2. Introspecting Objects

10.2.1. 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"""

localhost = Server(host='127.0.0.1', port=1337)

output = dir(localhost)
print(output)
# ['__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']

10.2.2. 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"""

localhost = Server(host='127.0.0.1', port=1337)

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

10.2.3. 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"""

localhost = Server(host='127.0.0.1', 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>
# }

10.2.4. hasattr(), getattr(), setattr()

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

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

        last_name = getattr(self, 'last_name', 'n/a')
        return f'My name... {first_name} {last_name}'


 jose = Astronaut(first_name='Jose', last_name='Jimenez')

 print(jose)
 # My name... Jose Jimenez

10.2.5. 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 ... ...

10.3. Introspecting Docstrings

10.3.1. 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"""

localhost = Server(host='127.0.0.1', port=1337)

help(localhost)
# 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)

10.3.2. 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"""

localhost = Server(host='127.0.0.1', port=1337)

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

10.4. Example

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 "%s.%s" % (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))