Python Introspection

From NovaOrdis Knowledge Base
Revision as of 04:04, 4 January 2023 by Ovidiu (talk | contribs) (→‎TODO)
Jump to navigation Jump to search

Internal

Overview

Introspection is Python's equivalent for Java reflection. It is the ability to determine the type of an object at runtime and to dynamically examine Python objects.

Introspect Members of an Object Instance

All members of an object instance can be identified using inspect.getmembers(). It its most generic form, without any argument, the function returns all members of an object instance as (name, value) tuples, sorted by name. The result will include the reference to the object instance's class, as __class__, instance attributes, methods, etc.:

import inspect

class SampleClass:
    def __init__(self):
        self.color = 'blue'

i = SampleClass()

print(f'{"name".ljust(17)} {"value".ljust(83)} value type')

for (name, value) in inspect.getmembers(i):
    print(f'{name.ljust(17)} {str(value).ljust(83)} {str(type(value))}')

produces:

name              value                                                                               value type
__class__         <class '__main__.SampleClass'>                                                      <class 'type'>
__delattr__       <method-wrapper '__delattr__' of SampleClass object at 0x109144190>                 <class 'method-wrapper'>
__dict__          {'color': 'blue'}                                                                   <class 'dict'>
__dir__           <built-in method __dir__ of SampleClass object at 0x109144190>                      <class 'builtin_function_or_method'>
__doc__           None                                                                                <class 'NoneType'>
__eq__            <method-wrapper '__eq__' of SampleClass object at 0x109144190>                      <class 'method-wrapper'>
__format__        <built-in method __format__ of SampleClass object at 0x109144190>                   <class 'builtin_function_or_method'>
__ge__            <method-wrapper '__ge__' of SampleClass object at 0x109144190>                      <class 'method-wrapper'>
__getattribute__  <method-wrapper '__getattribute__' of SampleClass object at 0x109144190>            <class 'method-wrapper'>
__gt__            <method-wrapper '__gt__' of SampleClass object at 0x109144190>                      <class 'method-wrapper'>
__hash__          <method-wrapper '__hash__' of SampleClass object at 0x109144190>                    <class 'method-wrapper'>
__init__          <bound method SampleClass.__init__ of <__main__.SampleClass object at 0x109144190>> <class 'method'>
__init_subclass__ <built-in method __init_subclass__ of type object at 0x7faabab12f60>                <class 'builtin_function_or_method'>
__le__            <method-wrapper '__le__' of SampleClass object at 0x109144190>                      <class 'method-wrapper'>
__lt__            <method-wrapper '__lt__' of SampleClass object at 0x109144190>                      <class 'method-wrapper'>
__module__        __main__                                                                            <class 'str'>
__ne__            <method-wrapper '__ne__' of SampleClass object at 0x109144190>                      <class 'method-wrapper'>
__new__           <built-in method __new__ of type object at 0x10984c950>                             <class 'builtin_function_or_method'>
__reduce__        <built-in method __reduce__ of SampleClass object at 0x109144190>                   <class 'builtin_function_or_method'>
__reduce_ex__     <built-in method __reduce_ex__ of SampleClass object at 0x109144190>                <class 'builtin_function_or_method'>
__repr__          <method-wrapper '__repr__' of SampleClass object at 0x109144190>                    <class 'method-wrapper'>
__setattr__       <method-wrapper '__setattr__' of SampleClass object at 0x109144190>                 <class 'method-wrapper'>
__sizeof__        <built-in method __sizeof__ of SampleClass object at 0x109144190>                   <class 'builtin_function_or_method'>
__str__           <method-wrapper '__str__' of SampleClass object at 0x109144190>                     <class 'method-wrapper'>
__subclasshook__  <built-in method __subclasshook__ of type object at 0x7faabab12f60>                 <class 'builtin_function_or_method'>
__weakref__       None                                                                                <class 'NoneType'>
color             blue                                                                                <class 'str'>

Introspect Members of an Object Instance Filtering with Predicates

inspect.getmembers() accepts a predicate as the second argument. The predicate is a function applied to the value that must return true or false. The inspect package comes with several predefined predicates:

Predicate Description
inspect.isclass Return true if the value of the member is a class
inspect.ismethod Return true if the value of the member is an instance method
inspect.ismodule Return true if the value of the member is a module
import inspect

class SampleClass:
    def __init__(self):
        self.color = 'blue'

    def some_method(self):
        print('some_method')

i = SampleClass()

for (name, value) in inspect.getmembers(i, inspect.ismethod):
    print(f' method name: {name}')

will display:

method name: __init__
method name: some_method

inspect Standard Library Module

https://docs.python.org/3/library/inspect.html#module-inspect

inspect is a Standard Library module.

getattr()

getattr() is a built-in function that returns the value of the specified attribute from the specified object. If an attribute with such name does not exist, an AttributeError exception is thrown.

Class Introspection with getattr()

A specific static method can be identified by querying the class attributes with inspect.getmembers() and selecting the matching method, or by name with getattr() builtin.

cls = ...
method_name = 'some_static_method'
try:
  method = getattr(cls, method_name)
  print(method)
except AttributeError:
  print(f"{method_name} method not found in class {cls}")

Invoke Functions and Methods Dynamically

Dynamic Invocation

Specialized Introspection

Module Internal Representation and Introspection

Module Internal Representation and Introspection