Explain Codes LogoExplain Codes Logo

Print all properties of a Python Class

python
object-oriented-programming
data-serialization
pretty-printing
Anton ShumikhinbyAnton Shumikhin·Sep 24, 2024
TLDR

To output all properties of a Python class instance, use vars() or __dict__. Here's an example:

class MyClass: prop1 = "value1" prop2 = "value2" obj = MyClass() for prop, value in vars(obj).items(): print(f"{prop} = {value}")

This will print:

prop1 = value1
prop2 = value2

In this case, vars(obj) or obj.__dict__ both convert the object's properties into a dictionary format, thus enabling you to print them easily.

Developing further: Complex classes

For more complex classes featuring methods, static variables etc., you might want to leave these out from the printed properties. Use dir() along with a list comprehension to achieve that:

# Who knew Python had a hidden filter function? Let's steal it [obj.__dict__[attr] for attr in dir(obj) if not attr.startswith('__') and not callable(getattr(obj, attr))]

Here we're filtering out methods and 'magic' attributes, that include double underscores, to give a cleaner property list.

Persistent storage: Shelve it!

For storing class properties persistently, Python's shelve module comes handy. It allows you to store the class instances directly, no need for manual dictionary conversion:

import shelve # Making our class shelf-ready class MyClass: prop1 = "value1" prop2 = "value2" obj = MyClass() # Shelf life begins with shelve.open('myclass.db') as db: db['obj'] = obj # And retrieving the data is as easy as a Sunday morning loaded_obj = db['obj'] print(loaded_obj.prop1) # Output: value1

Ppretty please: Printing with style

ppretty is a third-party library that promises (and delivers!) beautifully formatted printouts:

from ppretty import ppretty # Things are about to show some ppretty serious changes print(ppretty(obj))

This comes in handy when debugging or in need of a user-friendly representation of an object's properties.

Hidden attributes: Pulling back the curtain

Classes with custom getter/setter methods won't expose their attributes via __dict__. Here, implementing a custom method is the way to go:

class MyClass: def __init__(self): # Undercover property self._prop1 = "value" @property def prop1(self): # Official presentation return self._prop1 # Just a casual class instance passing by. Nothing to see here obj = MyClass() # Okay, just a little peek props = {name: getattr(obj, name) for name in dir(obj) if isinstance(getattr(type(obj), name, None), property)} print(props) # [{'prop1': 'value'}]

This goes straight to the properties via their public interface, avoiding any unwanted attention to the underlying data.

Handling the big guns: Scalability

When the classes have a large number of attributes, decorators or metaprogramming techniques can help avoid the manual labor:

def auto_repr(cls): # Auto-creating __repr__ def __repr__(self): # Take all the properties and line them up nicely for the show properties = ', '.join([f"{name}={value}" for name, value in vars(self).items()]) return f"{cls.__name__}({properties})" cls.__repr__ = __repr__ return cls # Just decorating my class here, don't mind me. @auto_repr class MyClass: prop1 = "value1" prop2 = "value2"

The auto_repr decorator appends a custom string representation method, that automatically lists all properties, to any class it gets applied to.