##  [Getting started with classes in Python Part 9: `\_\_str\_\_` vs `\_\_repr\_\_`](/blog/getting-started-classes-python-part-9-str-vs-repr) 

In Part 8 we introduced the concept of dunder methods and mentioned how they are used "under the hood" to perform much of the day-to-day business logic Python does behind the scenes. In this Part we will delve a little into a simple example of how to leverage two in particular.

In all classes there are two simple dunder methods called `__str__` which is called whenever a class is turned into a string (hence the `str`) and `__repr__` which is called whenever a representation of the class is needed. This is typically when a visual representation of the class is needed (this may sound similar to `__str__` but it is subtly not as will be explained shortly). Each just returns a string, usually based on what's in the class. What's the difference? Well it's actually quite simple. The `repr` is for when something is returned visually but *not* printed. For example, if you are doing python in an interactive interpreter and output an object you will see that object's `repr`, but if you *print* the object with the `print()` function you will see the object's `str`.

There are two rules that come out of this.

1. The `__str__` method should be a useful visual representation of the class instance
2. The `__repr__` method should show what the class is, and ideally how to create this instantiation yourself. Ideally, it should be evaluatable code.

For example, below is a class I used for [Advent of Code 2024 Day 10](https://adventofcode.com/2024/day/10). The code snippet actually contains *two* classes, `Tile` and `Point`. Dataclasses in Python actually provide a built-in `str` and `repr` function that renders exactly what the class is and what each of the properties are.

```python
from dataclasses import dataclass


@dataclass
class Point:
    x: int
    y: int


@dataclass
class Tile:
    point: Point
    height: str


tile = Tile(Point(0, 0), '0')
print(tile)

```

Printing out the instance of `tile` produces this output.

```text
Tile(point=Point(x=0, y=0), height='0')

```

This is a perfect `repr` because if you were to copy and paste that code into the program it would create the object it came from. But as a `str` method result? It's quite verbose. However in the challenge we're going to have a *lot* of these tiles and this is unnecessarily verbose for the output too. What if instead of one we had to print out 500?

We can create a `str` method instead that makes the output more compact and to do so, we only need to add two lines to our existing script.

```python
from dataclasses import dataclass


@dataclass
class Point:
    x: int
    y: int


@dataclass
class Tile:
    point: Point
    height: str

    def __str__(self) -&gt; str:
        return f'(x:{self.point.x}-y:{self.point.y}-h:{self.height})'


tile = Tile(Point(0, 0), '0')
print(tile)

```

Now if we print `tile` we see the following output, which is a lot shorter and keeps the same amount of information available.

```text
(x:0-y:0-h:0)

```

This is a pretty simple trick but the benefits are significant and can make UX and debugging significantly easier. Next time, in Part 10, we're going to tackle a topic I've been putting off, because it's a tricky subject, and we're finally ready to talk about it: inheritance.

#### Take a Step Back?

If you haven't already read the previous articles in this series, you may want to take a step back to look at some of the information that has brought us to this point. For a complete look at the articles in this series, you can visit the overview page: [Getting started with classes in Python](https://developer.ansys.com/blog/getting-started-classes-python)

Or, if you want to look directly at a particular previous article, here are the links:

- [Part 1](https://developer.ansys.com/blog/getting-started-classes-python-part-1-anatomy-class): Anatomy of a Class
- [Part 2](https://developer.ansys.com/blog/getting-started-classes-python-part-2-dataclasses-0): `dataclasses`
- [Part 3](https://developer.ansys.com/blog/getting-started-classes-python-part-3-methods-and-properties): Methods and properties
- [Part 4](https://developer.ansys.com/blog/getting-started-classes-python-part-4-hashing-mutability): Hashing &amp; Mutability
- [Part 5](https://developer.ansys.com/blog/getting-started-classes-python-part-5-classmethod-and-staticmethod): `classmethod` and `staticmethod`
- [Part 6](https://developer.ansys.com/blog/getting-started-classes-python-part-6-public-private-and-super-private-naming): Public, Private and Super-Private Naming
- [Part 7](https://developer.ansys.com/blog/getting-started-classes-python-part-7-getters-and-setters): getters and setters
- [Part 8](https://developer.ansys.com/blog/getting-started-classes-python-part-8-dunder): dunder methods