Python's __repr__ method when __init__ takes an array as argument

968 views Asked by At

I am quite new to OOP with Python, and trying to understand how the __repr__ method should output in this particular instance.

When initialising the Playlist class, an array, containing song objects, can be passed as an argument. You can also pass nothing as an argument, and add songs objects to a playlist using a separate add_song method.

However I'm not quite sure how to set up my __repr__ method in this case. If I pass an array of 10+ song objects, the output of repr method would be extremely large - as each song object itself has several parameters.

Is there a Pythonic way of doing this?

EDIT: To make my question less vague - from what I understand, the repr method is intended to return a string representation of an object. In my case, Playlist objects are passed an array as an argument (or nothing at all). If an array is passed, this contains song objects, which themselves have a number of parameters such as name of song, language of song, etc. My question is whether there is a 'correct' way to set up the repr method in this instance - or if this is really just up to me to decide.

class Playlist:
        
        def __init__(self, songs = None):
            if songs is None:
                self.playlist = []
            else:
                self.playlist = songs
                
        def __repr__(self):
            return (f"{self.__class__.__name__}({self.playlist})")

Output of printing a playlist object:

Playlist([Song(Random Song Name 1, English, 50), Song(Random Song Name 2, English, 25)])

2

There are 2 answers

8
AudioBubble On

__repr__ in Python

Source

According to the official Python documentation, __repr__ is a built-in function used to compute the “official” string reputation of an object,

__repr__ should be return a string representation of your object. This is useful for debugging. That means you should return all the attributes of a class in a way you would prefer.

Example

class Entity:
    def __init__(self,name):
        self.name = name
    def __repr__(self):
        return "Name: " + self.name

From your example, you need to return the names of the songs and their ID's.

def __repr__(self):
    songs = ""
    for i in range(len(playlist)):
        songs+=f"{i+1}. {playlist[i]}"
    return songs

This is how I would do it. You are free to choose the output format. I am pretty sure you must have more attributes in this class. You shall return them in this function.

From your question

It is true that if you have a huge list of songs for an object the string representation could be huge. A good way must be to make the string representation more organized and hence easier to read. Something like

     Object x
Song 1 : 
   Name: name
   Artist: artist
   Length: length
   

The point of this method is that you can call it whenever you want and get all the attributes of the object, Suppose you have an issue regarding the artist being displayed incorrectly. A good start of debugging can be to display the object attributes in an organized manner so you can trace back to exactly where the problem comes from.

  • You could split the songs into the different genres/artist and print them separately
  • Take it one step further by writing the string into a file so you can read everything peacefully. It's all up to you.
2
tdelaney On

Its up to you. repr should return a string that gives greater typing information than the more human friendly str. If size gets in the way, you are free to fix that the way you think is best. For instance, pandas gives you an abbreviated view that contains other details such as the full dimension.

>>> df=pd.DataFrame([list(range(5)) for _ in range(500)])
>>> print(repr(df))
     0  1  2  3  4
0    0  1  2  3  4
1    0  1  2  3  4
2    0  1  2  3  4
3    0  1  2  3  4
4    0  1  2  3  4
..  .. .. .. .. ..
495  0  1  2  3  4
496  0  1  2  3  4
497  0  1  2  3  4
498  0  1  2  3  4
499  0  1  2  3  4

[500 rows x 5 columns]

Its okay to do the same thing with songs.