printing __str__ of elements in a list

Question:

I’ve learned that __str__ can define an output of the string of the object.

Example:

class Person(object):
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return self.name

p1 = Person('Steve Jobs')
p2 = Person('Bill Gates')
p3 = Person('Mark Zuckerberg')

print(p1)  # >>> Steve Jobs

it output Steve Jobs as I wished, instead of <__main__.Person object at 0x10410c588>

However, if I create a list:

lst = [p1, p2, p3]
print(lst)
# >>> [<__main__.Person object at 0x1045433c8>, <__main__.Person object at 0x1045434e0>, <__main__.Person object at 0x104543550>]

I have to :

print([i.__str__() for i in lst])
# >>> ['Steve Jobs', 'Bill Gates', 'Mark Zuckerberg']

to make it work??

This does not make sense much, right?

Asked By: jxie0755

||

Answers:

The list.__str__ uses the object’s __repr__ to build the string. So, just delegate __repr__ to __str__:

In [1]: class Person(object):
   ...:     def __init__(self, name):
   ...:         self.name = name
   ...:     def __str__(self):
   ...:         return self.name
   ...:     def __repr__(self):
   ...:         return str(self)
   ...:
   ...: p1 = Person('Steve Jobs')
   ...: p2 = Person('Bill Gates')
   ...: p3 = Person('Mark Zuckerberg')
   ...:

In [2]: print(p1)
Steve Jobs

In [3]: lst = [p1, p2, p3]
   ...:

In [4]: print(lst)
[Steve Jobs, Bill Gates, Mark Zuckerberg]

EDIT

If you want to stick to convention, do somthing like:

In [18]: class Person(object):
    ...:     def __init__(self, name):
    ...:         self.name = name
    ...:     def __str__(self):
    ...:         return self.name
    ...:     def __repr__(self):
    ...:         return f"{type(self).__name__}({self.name})"
    ...:

In [19]: p1 = Person('Steve Jobs')

In [20]: print([p1])
[Person(Steve Jobs)]
Answered By: juanpa.arrivillaga

Consider implementing:

class Person(object):
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return self.name
    def __repr__(self):
        return 'Person({!r})'.format(self.name)  # !r adds the quotes correctly

Which gives:

>>> lst
[Person('Steve Jobs'), Person('Bill Gates'), Person('Mark Zuckerberg')]

The reason you’re seeing mismatching behavior is that print calls str() on its argument, but list str and repr are the same, and both call repr on each element.

Answered By: Eric
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.