Python Introspection: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
Line 22: Line 22:
produces:
produces:
<font size=-1>
<font size=-1>
name              value                                                                              value type
name              value                                                                              value type
__class__        <class '__main__.SampleClass'>                                                      <class 'type'>
__class__        <class '__main__.SampleClass'>                                                      <class 'type'>
__delattr__      <method-wrapper '__delattr__' of SampleClass object at 0x109144190>                <class 'method-wrapper'>
__delattr__      <method-wrapper '__delattr__' of SampleClass object at 0x109144190>                <class 'method-wrapper'>
__dict__          {'color': 'blue'}                                                                  <class 'dict'>
__dict__          {'color': 'blue'}                                                                  <class 'dict'>
__dir__          <built-in method __dir__ of SampleClass object at 0x109144190>                      <class 'builtin_function_or_method'>
__dir__          <built-in method __dir__ of SampleClass object at 0x109144190>                      <class 'builtin_function_or_method'>
__doc__          None                                                                                <class 'NoneType'>
__doc__          None                                                                                <class 'NoneType'>
__eq__            <method-wrapper '__eq__' of SampleClass object at 0x109144190>                      <class 'method-wrapper'>
__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'>
__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'>
__ge__            <method-wrapper '__ge__' of SampleClass object at 0x109144190>                      <class 'method-wrapper'>
__getattribute__  <method-wrapper '__getattribute__' 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'>
__gt__            <method-wrapper '__gt__' of SampleClass object at 0x109144190>                      <class 'method-wrapper'>
__hash__          <method-wrapper '__hash__' 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__          <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'>
__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'>
__le__            <method-wrapper '__le__' of SampleClass object at 0x109144190>                      <class 'method-wrapper'>
__lt__            <method-wrapper '__lt__' of SampleClass object at 0x109144190>                      <class 'method-wrapper'>
__lt__            <method-wrapper '__lt__' of SampleClass object at 0x109144190>                      <class 'method-wrapper'>
__module__        __main__                                                                            <class 'str'>
__module__        __main__                                                                            <class 'str'>
__ne__            <method-wrapper '__ne__' of SampleClass object at 0x109144190>                      <class 'method-wrapper'>
__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'>
__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__        <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'>
__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'>
__repr__          <method-wrapper '__repr__' of SampleClass object at 0x109144190>                    <class 'method-wrapper'>
__setattr__      <method-wrapper '__setattr__' 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'>
__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'>
__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'>
__subclasshook__  <built-in method __subclasshook__ of type object at 0x7faabab12f60>                <class 'builtin_function_or_method'>
__weakref__      None                                                                                <class 'NoneType'>
__weakref__      None                                                                                <class 'NoneType'>
color            blue                                                                                <class 'str'>
color            blue                                                                                <class 'str'>
</font>
</font>



Revision as of 03:11, 4 January 2023

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,

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'>

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}")

The inspect Standard Library Module

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

inspect is a Standard Library module.

getmembers()

getmembers() returns all members of an object as (name, value) pairs sorted by name. The object can be a module, class, etc. A predicate can be provided to the function, and the function returns only return members that satisfy a given predicate.

Module Introspection with getmembers()

Also see:

Python Language Modularization

Find classes in a module:

import inspect

module = sys.modules['some_package.some_subpackage.SomeClass']
class_tuples = inspect.getmembers(module, inspect.isclass)
for ct in class_tuples:
  print('class name: ', ct[0])
  print('class: ', ct[1])

Invoking Functions and Methods Dynamically

Dynamic Invocation

TODO

https://www.geeksforgeeks.org/code-introspection-in-python/

Module Internal Representation and Introspection

Module Internal Representation and Introspection