Python: Classes: String Representation

Hi Team

class Circle:
  pi = 3.14
  
  def __init__(self, diameter):
    self.radius = diameter / 2
  
  def area(self):
    return self.pi * self.radius ** 2
  
  def circumference(self):
    return self.pi * 2 * self.radius
 
  def __repr__(self):
    return 'Circle with radius' + ' ' + str(self.radius)
  
medium_pizza = Circle(12)
teaching_table = Circle(36)
round_room = Circle(11460)

print(medium_pizza)
print(teaching_table)
print(round_room)

This is an exercise I have done that teaches string representation. My question is more to understand the use of this method ( and to understand it better).

  1. Why does python have this dunder to get the object representation. Couldn’t the coding be made simpler if a print(object) just printed the stored value anyway, reducing a dunder.

  2. If a coder needed to see the location and class data of the object he/she could call it explicitly with another command?? As a coder don’t we need the stored value more often than the default representation.

  3. Do you reckon this will be improved in next python update?

  4. If my questions are not that valid than how does default representation of an object valuable/ worthy in the coding or later stages?

All of this coz I was thinking its bit redundant having to call a repr dunder to get the value when the an update can easily make it straightforward. Please let me know if the community feels the same.

Thank you

When you ask a question, don’t forget to include a link to the exercise or project you’re dealing with!

If you want to have the best chances of getting a useful answer quickly, make sure you follow our guidelines about how to ask a good question. That way you’ll be helping everyone – helping people to answer your question and helping others who are stuck to find the question and answer! :slight_smile:

Hi @rdb20,

Objects that are defined by programmers can range from very simple ones that do not store any values to very complex ones that store many values. Some objects may store other objects as values. Given that wide variety of possibilities, what general rule could be established for representing an object other than the existing one?

Link to exercise: Learn Python: Classes: String Representation

Hi - but in a code, while it runs,( in its scope) if the values can be shown instead of default representation - and i believe that changes as well ( new value - means new storage location etc) - that would cut down using a dunder - to simplify the whole question - -------

Why is repr dunder important? Is it replaceable with further revisions to Python?

Why is default representation important when a coder does not use it that often ?

Thank you

As this discussion continues, it should be noted that what the default representation of a Python object should be is a matter of opinion. Evidently, the designers of Python have decided that this default should be rather minimal. That is also my own opinion.

Let’s consider the following class definitions, copied from my own code in the Veneer project script.py file:

class Artist:
  def __init__(self, last_name, first_name, year_born, year_died = None):
    self.last_name = last_name
    self.first_name = first_name
    self.year_born = year_born
    self.year_died = year_died
  def __repr__(self):
    return "{}, {}".format(self.last_name, self.first_name)

class Art:
  def __init__(self, artist, title, medium, year, owner):
    self.artist = artist
    self.title = title
    self.medium = medium
    self.year = year
    self.owner = owner
  def __repr__(self):
    return "{}. \"{}\". {}, {}. {}, {}. {}.".format(self.artist, self.title, self.year, self.medium, self.owner.name, self.owner.location, "Museum" if self.owner.is_museum else "Private Collection")
  
class Listing:
  def __init__(self, art, price, seller):
    self.art = art # Art
    self.price = price
    self.seller = seller # Client
  def __repr__(self):
    return "{} {}".format(self.art.title, self.price)
  
class Marketplace:
  # Variation on instruction 8
  def __init__(self, listings = []):
    self.listings = listings
    # self.listings = []
  def add_listing(self, new_listing):
    self.listings.append(new_listing)
  def remove_listing(self, listing):
    self.listings.remove(listing)
  def show_listings(self):
    print("Listings:")
    for listing in self.listings:
      print(listing)
    print("End of listings")

See Computer Science: Veneer

Note that a Marketplace instance contains a list of Listing instances. A Listing instance contains an Art instance. That Art instance contains, in turn, an Artist instance. The relationship between the classes is somewhat complex.

With there being no __repr__ method for the Marketplace class, what would be a reasonable default representation of a Marketplace instance?

2 Likes

Just the class it belongs tpo with stored location - is that right?

Also, the class names all start with capital letter, like Art , Listing — but while using it to interact with other method you use art.title ----- doesn’t that give an error?

Yes, that would be the default, as it is currently defined by Python. However, in the quote below, you suggest that it would be better for the default to be something else. We need to think about what that better default would entail.

In the case of an instance of a complex class, such as Marketplace that includes references to instances of other classes, what information would you recommend that Python display by default to represent the stored value, when the instance is passed to the print function?

No, Art and Listing are names of classes, but art and listing are names of parameters of certain methods. Those parameters are there to represent instances of the classes that have similar names.

1 Like

One reason, really: debugging.

An easy way of checking what your program is doing at any given point in time is to throw stuff to the console - print(some_variable), for example.

If some_variable is a built-in type, like a list, you get a nice and easily understandable representation of the object:

some_variable = [5, 32, 'cheese', ['sub','list']]
print(some_variable) # prints: [5, 32, 'cheese', ['sub', 'list']]

You can see, at a glance, what’s going on inside your variable. If possible, the __repr__ should give you a Python statement you can use to recreate that variable (like with the list!)

With your custom classes, Python has no idea how best to express what could be a convoluted object in a meaningful way. The default representation, of <__main__.dummy object at 0x0> doesn’t tell you anything meaningful about the state of that object. You know that it’s an instance of an object, that’s it.

That’s useless for debugging, same as seeing <__main__.list object at 0x0> or <__main__.int object at 0x0> would be.

2 Likes