Search code examples
pythonpython-dataclasses

How can I overwrite the default print output of a python dataclass?


Given the InventoryItemexample from the dataclasses documentation.

from dataclasses import dataclass

@dataclass
class InventoryItem:
    """Class for keeping track of an item in inventory."""
    name: str
    unit_price: float
    quantity_on_hand: int = 0

InventoryItem(name="Banana", unit_price=5, quantity_on_hand=3)

# OUTPUT:
# InventoryItem(name='Banana', unit_price=5, quantity_on_hand=3)

How to overwrite the standard output message such that the output string

"3 Banana(s) at a unit price of 5."

is displayed?


Solution

  • First of all, dataclasses are normal classes. There is no such a thing as a dataclass type.

    There are two ways to override the standard output message of any Python class:

    • define the __repr__ method

      In Python's data model this method is...

      ... the “official” string representation of an object. If at all possible, this should look like a valid Python expression that could be used to recreate an object with the same value.

      The representation that you want is not a valid expression to recreate the object, so this is not a good choice.

    • define the __str__ method

      Again from the data model:

      Called by str(object) and the built-in functions format() and print() to compute the “informal” or nicely printable string representation of an object. [...] This method differs from object.__repr__() in that there is no expectation that __str__() return a valid Python expression.

      This is what I would recommend using.

    from dataclasses import dataclass
    
    @dataclass
    class InventoryItem:
        """Class for keeping track of an item in inventory."""
        name: str
        unit_price: float
        quantity_on_hand: int = 0
        
        def __str__(self):
            return f"{self.quantity_on_hand} {self.name}(s) at a unit price of {self.unit_price}"
    
    >>> item = InventoryItem(name="Banana", unit_price=5, quantity_on_hand=3)
    >>> item  # __repr__ being called
    InventoryItem(name='Banana', unit_price=5, quantity_on_hand=3)
    >>> print(item)  # __str__ being called
    3 Banana(s) at a unit price of 5