There is some API, the function call returns an object. The object has an unknown structure to me.

Google suggests that there are many ways of introspection. Is there a standard way to display the structure of an object? Specifically, I care about the fields of the object - their types and names.

Used __dict__ , result:

 {'this': <Swig Object of type 'table_ptr_t *' at 0x0000000002724210>} 

If the object is generated by SWIG, can I get the structure of the object?

  • The function dir , for example. - m9_psy
  • If you are given an exhaustive answer, mark it as correct (a daw opposite the selected answer). - Nicolas Chabanovsky

2 answers 2

 import inspect, sys filter_is = [a for a in dir(inspect) if a.startswith('is')] class B: Z = range(4) def attr(self, a: [Z, Z.__class__.__name__], z, *args, x=Z, y='y5', **kwargs): pass class A(B): def __init__(self): self.Y = 1, 2, 3 @classmethod def attr2(cls: object) -> str: pass @staticmethod def attr1(): pass c = A() a = c.__class__ print(inspect.classify_class_attrs(a)) print(inspect.getclasstree(inspect.getmro(a))) print(inspect.getmembers(с)) for an in dir(c): if not an.startswith('_'): ga = getattr(c, an) print('-' * 20) print(dict(name=an, type=type(ga), id=id(ga), len=len(ga) if hasattr(ga, '__len__') else None, getsizeof=sys.getsizeof(ga), getrefcount=sys.getrefcount(ga))) print({k: getattr(inspect, k)(ga) for k in filter_is}) print(ga) if callable(ga): print(inspect.getsource(ga)) print(inspect.getfullargspec(ga)) print(inspect.formatargspec(*inspect.getfullargspec(ga))) 

out:

 Attribute(name='Z', kind='data', defining_class=<class '__main__.B'>, object=range(0, 4)), Attribute(name='__class__', kind='data', defining_class=... [(<class 'object'>, ()), [(<class '__main__.B'>, (<class 'object'>,)), [(<class '__main__.A'>, (<class '__main__.B'>,))]]] [('Y', (1, 2, 3)), ('Z', range(0, 4)), ('__class__', <class '__main__.A'>), ('__delattr__', <method-wrapper '__delattr__' of A object at 0x029C94B0>), ('__dict__', {'Y': (1, 2, 3)}),..... -------------------- {'type': <class 'tuple'>, 'name': 'Y', 'len': 3, 'getsizeof': 40, 'id': 9584592, 'getrefcount': 4} {'isclass': False, 'ismethod': False, 'istraceback': False, 'isabstract': False, 'ismethoddescriptor': False, 'isfunction': False, 'isgenerator': False, 'ismodule': False, 'isroutine': False, 'isdatadescriptor': False, 'iscode': False, 'isframe': False, 'isgetsetdescriptor': False, 'isgeneratorfunction': False, 'isbuiltin': False, 'ismemberdescriptor': False} (1, 2, 3) -------------------- {'type': <class 'range'>, 'name': 'Z', 'len': 4, 'getsizeof': 24, 'id': 9225184, 'getrefcount': 5} {'isclass': False, 'ismethod': False, 'istraceback': False, 'isabstract': False, 'ismethoddescriptor': False, 'isfunction': False, 'isgenerator': False, 'ismodule': False, 'isroutine': False, 'isdatadescriptor': False, 'iscode': False, 'isframe': False, 'isgetsetdescriptor': False, 'isgeneratorfunction': False, 'isbuiltin': False, 'ismemberdescriptor': False} range(0, 4) -------------------- {'type': <class 'method'>, 'name': 'attr', 'len': None, 'getsizeof': 36, 'id': 9017304, 'getrefcount': 2} {'isclass': False, 'ismethod': True, 'istraceback': False, 'isabstract': False, 'ismethoddescriptor': False, 'isfunction': False, 'isgenerator': False, 'ismodule': False, 'isroutine': True, 'isdatadescriptor': False, 'iscode': False, 'isframe': False, 'isgetsetdescriptor': False, 'isgeneratorfunction': False, 'isbuiltin': False, 'ismemberdescriptor': False} <bound method A.attr of <__main__.A object at 0x009394B0>> def attr(self, a: [Z, Z.__class__.__name__], z, *args, x=Z, y='y5', **kwargs): pass FullArgSpec(args=['self', 'a', 'z'], varargs='args', varkw='kwargs', defaults=None, kwonlyargs=['x', 'y'], kwonlydefaults={'y': 'y5', 'x': range(0, 4)}, annotations={'a': [range(0, 4), 'range']}) (self, a: [range(0, 4), 'range'], z, *args, x=range(0, 4), y='y5', **kwargs) -------------------- {'type': <class 'function'>, 'name': 'attr1', 'len': None, 'getsizeof': 72, 'id': 33140928, 'getrefcount': 3} {'isclass': False, 'ismethod': False, 'istraceback': False, 'isabstract': False, 'ismethoddescriptor': False, 'isfunction': True, 'isgenerator': False, 'ismodule': False, 'isroutine': True, 'isdatadescriptor': False, 'iscode': False, 'isframe': False, 'isgetsetdescriptor': False, 'isgeneratorfunction': False, 'isbuiltin': False, 'ismemberdescriptor': False} <function A.attr1 at 0x01F9B0C0> @staticmethod def attr1(): pass FullArgSpec(args=[], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={}) () -------------------- {'type': <class 'method'>, 'name': 'attr2', 'len': None, 'getsizeof': 36, 'id': 9017304, 'getrefcount': 2} {'isclass': False, 'ismethod': True, 'istraceback': False, 'isabstract': False, 'ismethoddescriptor': False, 'isfunction': False, 'isgenerator': False, 'ismodule': False, 'isroutine': True, 'isdatadescriptor': False, 'iscode': False, 'isframe': False, 'isgetsetdescriptor': False, 'isgeneratorfunction': False, 'isbuiltin': False, 'ismemberdescriptor': False} <bound method type.attr2 of <class '__main__.A'>> @classmethod def attr2(cls: object) -> str: pass FullArgSpec(args=['cls'], varargs=None, varkw=None, defaults=None, kwonlyargs=[], kwonlydefaults=None, annotations={'cls': <class 'object'>, 'return': <class 'str'>}) (cls: object) -> str 
  • def attr1 (self, x: int ): - Does Python do this? - veryStupidJunior
  • no, this is an annotation, type checking does not happen - vadim vaduxa
  • @veryStupidJunior, type checking can be done by third-party tools, as part of the IDE (for example, PyCharm) or separately ( mypy ). - insolor
  • Is there an alternative to getfullargspec () in python 2.? - veryStupidJunior
  • inspect.getargspec () - vadim vaduxa

Specifically, I haven’t heard about the way of introspection of objects built into the standard python library, it is unlikely to exist.


Nevertheless, you can use debugging tools:

First there is a standard debugger .

Secondly , the pycharm development environment debugger perfectly and visually displays the structure of any object, with types, contents and everything else that we as users do not need at all. Highly recommend. It will remove a lot of unnecessary burden, as with the developer.

Thirdly , it is easy to write your object inspector. I do not think that it will take more than a dozen lines. Although so debugging, of course, will not be convenient.

Well, in the fourth , there is a debugger in IDLE, where only what is needed is displayed for beginners. The attributes of the necessary objects, right during the execution of the program, will not be difficult to see.

If the object is generated by SWIG, can I get the structure of the object?

I have not tried it, but in theory if the object is already in the sight of python, then there should be no problems.