1

Is there a way to programmatically determine an object's structure/model, it's constituent parts, how it can be iterated and manipulated and transformed, broken down and built back up?

Trial and error are great teachers. I take their classes every day. But here I'm looking for a way to "work smarter" or at least differently.

A little background: I recently spent way too many hours incorrectly handling a pandas groupby object because I did not understand the building block parts and types that it is made of. I did not correctly handle the tuple that is returned when iterating on a groupby object. I now have a slightly better, but not at all sufficient, understanding of this particular object: e.g., a groupby obj breaks down into "params" and "table" when iterated. table, in turn, is made up of index and rows. But I'm still not sure how to handle rows: what they're made of or break down into. This post includes code to reproduce the issue: see Edit 2 at the bottom of original post.

But this is a particular case; my question is more general. My question is, if I don't already know the structure or "model" of a python object/type, how can I query the object to reveal this information textually or, even better perhaps, graphically?


Edit:

For purposes of exploration and learning, below I try to run every str method on a str object via a for loop. The meth obj is interpreted correctly in the first two lines of the loop (e.g., __add__ and __class__), but is interpreted as meth when I try to run obj.meth. How can I fix this?

Input:

obj = 'my_string'

object_methods = [method_name for method_name in dir(obj)
                  if callable(getattr(obj, method_name))]

print(len(object_methods))
print(object_methods)

Output:

77
['__add__', '__class__', . . ., 'upper', 'zfill']

Input:

for meth in object_methods:
    print(meth)
    try:
        print('obj.meth for obj', obj, 'and method', meth, ':') 
        obj.meth
    except AttributeError as e:
        print('obj.meth for obj', obj, 'and method', meth, ': AttributeError:', e)

Output:

__add__
obj.meth for obj my_string and method __add__ :
obj.meth for obj my_string and method __add__ : AttributeError: 'str' object has no attribute 'meth'
__class__
obj.meth for obj my_string and method __class__ :
obj.meth for obj my_string and method __class__ : AttributeError: 'str' object has no attribute 'meth'
. . .
Karl Baker
  • 903
  • 12
  • 27

1 Answers1

3

You can use __dict___ and dir in order to see object model.

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

jack = Person('jack',23)
print(jack.__dict__)
print(dir(jack))

Output:

{'age': 23, 'name': 'jack'}
['__doc__', '__init__', '__module__', 'age', 'name']
balderman
  • 22,927
  • 7
  • 34
  • 52
  • `dir(obj)` gives me a list of attributes/methods, I've used that before. I tried `obj = 'string'`; `obj.__dict__` and got `AttributeError: 'str' object has no attribute '__dict__'`. In what contexts or for what types of objects does it work? – Karl Baker Feb 18 '19 at 08:02
  • From the docs: object.__dict__ A dictionary or other mapping object used to store an object’s (writable) attributes.See https://www.geeksforgeeks.org/reflection-in-python/ for more – balderman Feb 18 '19 at 17:39
  • I read the geeks post and am testing some code but getting errors which I added to my original post. Can you help me figure out how to fix this code? – Karl Baker Feb 18 '19 at 22:56