Reputation: 59
So I have the following function :
def find_by_name(self, name):
fitting_list = [p for p in self.__persons if name.lower() in p.name.lower()]
return fitting_list
And I get the following output when I want to print the list :
[<src.store.domain.person.Person object at 0x000001F88705B128>]
Why does this happen and how can I fix it?
Upvotes: 1
Views: 125
Reputation: 55469
list
doesn't care that your class has a __str__
method.
When you print an object, print
calls str
on the object to get a suitable string. The str
function attempts to call the object's __str__
method, but if it doesn't have one then it calls the object's __repr__
method instead. And if their isn't a definition for __repr__
in that object's class definition then you'll get the one inherited from the parent class, typically that will be the default __repr__
from the base object
type.
list
and the other built-in collections like tuple
, set
and dict
don't have a __str__
method, so when you try to convert them to strings (either explicitly using the str
function, or implicitly via print
) their __repr__
method is called. And those __repr__
methods in turn call repr
on each item in the collection. So when you pass any of those collection objects to print
you will always see the __repr__
of the items. And explictly calling str
on the collection will make no difference.
If you want to see the __str__
representation of the items in a list
or collection you will need to iterate over the collection, calling str
explicitly on each item.
Here's a tiny code snippet (suitable for Python 2 & 3) that illustrates these points.
from __future__ import print_function
class Test(object):
def __str__(self):
return 'Test str'
def __repr__(self):
return 'Test repr'
a = [Test(), Test()]
print(id(a.__repr__), id(a.__str__))
print(a, str(a), repr(a))
for u in a:
print(u, str(u), repr(u))
output
3075508812 3075508812
[Test repr, Test repr] [Test repr, Test repr] [Test repr, Test repr]
Test str Test str Test repr
Test str Test str Test repr
So if you want to be able to print a list of your objects as a single entity and have the object's strings be more human-friendly, you have a couple of choices:
Change the name of your __str__
method to __repr__
. This is the simplest way, and as I said earlier, the __repr__
will be used if a __str__
can't be found when the object gets passed to str
.
Leave the existing __str__
method alone and create a __repr__
that's more human-friendly. However, it's suggested that the __repr__
display useful info to a programmer who sees it, and if practical it's nice if the __repr__
string can be copy & pasted into the interpreter or script to recreate the object.
Leave the existing __str__
method alone and create a __repr__
that calls __str__
. While valid, this is a bit silly. A related strategy is to set __repr__
as a class attribute that references __str__
. See below for an example.
class Test(object):
def __str__(self):
return 'Test str'
__repr__ = __str__
Upvotes: 1
Reputation: 971
This is just the __repr__
of the object. The __repr__
is meant to be a machine readable representation of the object and you can change it by overiding it.
Upvotes: 3