Reflection in Python

Overview

Overview

What is Reflection?

In computer science, reflection is the ability of a computer program to examine, introspect, and modify its own structure and behaviour at runtime
Reflection in Wikipedia

Reflection vs Introspection?

Both are often used as synonymous, but a subtle difference exists:
Introspection refers to the ability of an object to examine itself.
Reflection includes the ability of an object to modify itself, not only to introspect.

dir() function

dir() function

Syntax


            dir([object])
        
Without arguments, return the list of names in the current local scope
If an argument is given, it attempt to return a list of valid attributes for that object
If the object has a method named __dir__(), this method will be called
dir() @python docs

Example


            class Person:
              def __init__(self, name, age):
                self.name = name
                self.age = age

            maria = Person("Maria Popova", 25)

            print(dir(maria))
        

            ['__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__', 'age', 'name']
        

We see Person object attributes, as well as these, inherited from the built-in object class and its bases

type() function

type() function

Syntax


            class type(object)
            class type(name, bases, dict)
        
With one argument, return the type of an object. The return value is a type object and generally the same object as returned by object.__class__.
With three arguments, return a new type object. This is essentially a dynamic form of the class statement.
type() @python docs

Examples

type(object):

                class Person:
                  def __init__(self, name, age):
                    self.name = name
                    self.age = age

                maria = Person("Maria Popova", 25)

                print(type(maria))
                # <class '__main__.Person'>
            
type(name, bases, dict):
Dynamically create Employee class

                Employee = type('Employee', (object,), dict())
                pesho = Employee()
                print(type(pesho))

                # <class '__main__.Employee'>
            

id() function

id() function

Syntax


                id(object)
            
Return the “identity” of an object.
This is an integer which is guaranteed to be unique and constant for this object during its lifetime.
Two objects with non-overlapping lifetimes may have the same id() value.
In CPython, id() returns the address of the object in memory.
Example:

                print(id(1))

                x = 1
                print(id(x))

                y=x
                print(id(y))

                #11065920
                #11065920
                #11065920
            

Attributes reflections

Attributes reflections

hasattr() - syntax


                hasattr(object, name)
            
Return True if the object has attribute with given name as string. False otherwise.
Use case: to check if an object has a specific attribute before accessing it to avoid AttributeError
Example:

                class Person:
                    def __init__(self, name):
                        self.name = name


                maria = Person("Maria")

                if hasattr(maria, "age"):
                    print(maria.age)
                else:
                    print("Attribute 'age' not found")

                # Output: Attribute 'age' not found

            

getattr() - syntax


                getattr(object, name[, default])
            
Return the value of the named attribute of object
If the named attribute does not exist, default is returned if provided. Otherwise AttributeError is raised.
Use case: to safely retrieve an attribute's value with a default fallback if the attribute is missing
Example:

                class Person:
                    def __init__(self, name):
                        self.name = name


                maria = Person("Maria")

                age = getattr(maria, "age", "Not specified")
                print(age)

                # Output: Not specified

            

setattr() - syntax


                setattr(object, name, value)
            
The arguments are an object, a string and an arbitrary value.
The string may name an existing attribute or a new attribute.
The function assigns the value to the attribute, provided the object allows it
Use case: when the attribute name is dynamic (e.g., coming from a variable or user input).
Example:

                class Person:
                  def __init__(self, name, age):
                    self.name = name
                    self.age = age

                maria = Person("Maria Popova", 25)

                attr_name = "surname"
                setattr(maria, attr_name, "Popova")

                print(getattr(maria, "surname"))

                # Popova
            

Instance and Subclass Checking in Python

isinstance()

Using isinstance() Function

The isinstance() function is used to check if an object is an instance of a specified class or a subclass thereof.
It returns True if the object is an instance of the class or subclass, otherwise False.
Use case: to check if an object is an instance of a specific class or a subclass before performing operations on it.
Example:

                class Animal:
                    pass


                class Dog(Animal):
                    pass


                d = Dog()

                if isinstance(d, Dog):
                    print("d is a Dog")  # Output: d is a Dog

                if isinstance(d, Animal):
                    print("d is also an Animal")  # Output: d is also an Animal

            

issubclass()

Using issubclass() Function

The issubclass() function is used to check if a specified class is a subclass of another class.
It returns True if the class is a subclass, otherwise False.
Use case: to check if a class is a subclass of another class before applying inheritance-dependent logic.
Example:

                class Animal:
                    pass

                class Dog(Animal):
                    pass

                print(issubclass(Dog, Animal))  # True
                print(issubclass(Dog, object))  # True (all classes inherit from object)
                print(issubclass(Animal, Dog))  # False
            

the inspect built-in module

the inspect built-in module

Overview

The inspect module provides several useful functions for:
type checking
getting source code
inspecting classes and functions
examining the interpreter stack
Reference: inspect — Inspect live objects

Example

Get a function name, within a function. Get the name of the object that called the function:

                import inspect

                def foo():
                  func_name = inspect.stack()[0][3]
                  caller_name = inspect.stack()[1][3]
                  print(f"I'm {func_name}.\n{caller_name} called me!")

                def bar(f):
                  f()

                bar(foo)

                # I'm foo.
                # bar called me!
            

These slides are based on

customised version of

Hakimel's reveal.js

framework