backend / python core / 04_introspection.md

Introspection in Python

3 min read source

Introspection in Python

Introspection in Python refers to the ability of a program to examine the type or properties of an object at runtime. It is a powerful feature of Python, leveraging its dynamic nature.


Key Features of Introspection

  1. Type Checking:

    • You can check the type of an object using the type() or isinstance() functions.
    • Example:
      x = 42
      print(type(x))  # Output: <class 'int'>
      print(isinstance(x, int))  # Output: True
  2. Inspecting Attributes and Methods:

    • Use the dir() function to list all attributes and methods of an object.
    • Example:
      print(dir(str))  # Lists all methods and attributes of the string class
  3. Getting Documentation:

    • Access an object’s documentation string using the help() function or .__doc__ attribute.
    • Example:
      print(help(len))  # Displays documentation for the `len` function
      print(str.__doc__)  # Displays the docstring of the string class
  4. Determining Base Classes:

    • Use the __bases__ attribute to find the base classes of a class.
    • Example:
      class MyClass:
          pass
      
      print(MyClass.__bases__)  # Output: (<class 'object'>,)
  5. Inspecting Module Contents:

    • Use dir() on a module to list its contents.
    • Example:
      import math
      print(dir(math))  # Lists all functions and constants in the math module
  6. Accessing Object Attributes:

    • Use getattr(), setattr(), and hasattr() to dynamically interact with attributes of an object.
    • Example:
      class MyClass:
          x = 10
      
      obj = MyClass()
      print(getattr(obj, 'x'))  # Output: 10
      setattr(obj, 'y', 20)
      print(hasattr(obj, 'y'))  # Output: True

Why Introspection is Useful

  • Debugging: Easily inspect objects to understand their properties and methods.
  • Dynamic Programming: Create adaptable and flexible programs that can handle unknown types at runtime.
  • Reflection: Perform operations like dynamically calling methods or inspecting classes.

Example: Introspection in Action

class Animal:
    def speak(self):
        return "I am an animal"

obj = Animal()

# Introspection example
print(type(obj))  # Output: <class '__main__.Animal'>
print(dir(obj))  # Lists all attributes and methods of the object
print(obj.speak())  # Output: I am an animal

Introspection allows Python programs to be highly dynamic and flexible by enabling runtime examination of objects. It is a cornerstone of Python’s dynamic typing and reflective capabilities.

```python
# Example 1: Type Checking
x = 42
print(type(x))  # Output: <class 'int'>
print(isinstance(x, int))  # Output: True

# Example 2: Inspecting Attributes and Methods
print(dir(str))  # Lists all methods and attributes of the string class

# Example 3: Getting Documentation
print(help(len))  # Displays documentation for the `len` function
print(str.__doc__)  # Displays the docstring of the string class

# Example 4: Determining Base Classes
class MyClass:
    pass

print(MyClass.__bases__)  # Output: (<class 'object'>,)

# Example 5: Inspecting Module Contents
import math
print(dir(math))  # Lists all functions and constants in the math module

# Example 6: Accessing Object Attributes
class MyClass:
    x = 10

obj = MyClass()
print(getattr(obj, 'x'))  # Output: 10
setattr(obj, 'y', 20)
print(hasattr(obj, 'y'))  # Output: True
print(obj.y)  # Output: 20

# Example 7: Introspection in Action
class Animal:
    def speak(self):
        return "I am an animal"

obj = Animal()

# Introspection example
print(type(obj))  # Output: <class '__main__.Animal'>
print(dir(obj))  # Lists all attributes and methods of the object
print(obj.speak())  # Output: I am an animal

Interview angle

  • “What introspection tools do you actually use?” - type, isinstance, dir, vars, getattr, and inspect for signatures and source. In debugging, inspect.signature and inspect.getsource answer most “what does this actually accept” questions faster than reading imports.
  • “How do frameworks use it?” - FastAPI reads type annotations from the signature to build validation and OpenAPI; pytest discovers fixtures by parameter name; ORMs read class attributes to build schemas. Introspection is what makes declarative Python APIs possible.
  • “When is it the wrong tool?” - when a Protocol or explicit registration would be clearer. Heavy runtime introspection makes code hard to follow statically and defeats type checkers.