140

In Java, if I call List.toString(), it will automatically call the toString() method on each object inside the List. For example, if my list contains objects o1, o2, and o3, list.toString() would look something like this:

"[" + o1.toString() + ", " + o2.toString() + ", " + o3.toString() + "]"

Is there a way to get similar behavior in Python? I implemented a __str__() method in my class, but when I print out a list of objects, using:

print 'my list is %s'%(list)

it looks something like this:

[<__main__.cell instance at 0x2a955e95f0>, <__main__.cell instance at 0x2a955e9638>, <__main__.cell instance at 0x2a955e9680>]

how can I get python to call my __str__() automatically for each element inside the list (or dict for that matter)?

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
benhsu
  • 5,346
  • 8
  • 39
  • 47
  • 3
    Just for reference, there is [PEP 3140: "str(container) should call str(item), not repr(item)"](https://www.python.org/dev/peps/pep-3140/), which got rejected. – Alexey Feb 03 '19 at 18:50
  • 2
    @Alexey I love the rejection reason "Guido said this would cause too much disturbance too close to beta". Date: 2008! And we are still suffering this to this day. – Ciro Santilli OurBigBook.com Feb 09 '23 at 12:44

8 Answers8

175

Calling string on a python list calls the __repr__ method on each element inside. For some items, __str__ and __repr__ are the same. If you want that behavior, do:

def __str__(self):
    ...
def __repr__(self):
    return self.__str__()
David Berger
  • 12,385
  • 6
  • 38
  • 51
  • 10
    Identifying `__str__` with `__repr__` usually does not agree with the [Python data model](https://docs.python.org/2/reference/datamodel.html#object.__repr__), so the list comprehension solution proposed by @daniel-lew is more pythonic. – 0 _ Apr 04 '14 at 01:13
  • 2
    No argument. I answered the question as asked, which is often how a newcomer to python wants to think of the problem, but that doesn't mean that's the best way to answer. – David Berger Apr 04 '14 at 05:17
  • 3
    Python should be consistent with it's own data model and do the same thing for all primitives and aggregates. – Terrence Brannon Apr 06 '17 at 16:18
  • 8
    I think the default behavior for python lists is plain wrong. I would expect that `str()` on a list returned `str()` for each of individual elements inside. – SuperGeo Jan 26 '18 at 14:09
  • 1
    Using `__repr__ = __str__` on the class level would be shorter. – The_spider Jul 25 '22 at 18:52
28

You can use a list comprehension to generate a new list with each item str()'d automatically:

print([str(item) for item in mylist])
Dan Lew
  • 85,990
  • 32
  • 182
  • 176
8

Two easy things you can do, use the map function or use a comprehension.

But that gets you a list of strings, not a string. So you also have to join the strings together.

s= ",".join( map( str, myList ) )

or

s= ",".join( [ str(element) for element in myList ] )

Then you can print this composite string object.

print 'my list is %s'%( s )
S.Lott
  • 384,516
  • 81
  • 508
  • 779
4

Depending on what you want to use that output for, perhaps __repr__ might be more appropriate:

import unittest

class A(object):
    def __init__(self, val):
        self.val = val

    def __repr__(self):
        return repr(self.val)

class Test(unittest.TestCase):
    def testMain(self):
        l = [A('a'), A('b')]
        self.assertEqual(repr(l), "['a', 'b']")

if __name__ == '__main__':
    unittest.main()
Horst Gutmann
  • 10,910
  • 2
  • 28
  • 31
3

I agree with the previous answer about using list comprehensions to do this, but you could certainly hide that behind a function, if that's what floats your boat.

def is_list(value):
    if type(value) in (list, tuple): return True
    return False

def list_str(value):
    if not is_list(value): return str(value)
    return [list_str(v) for v in value]

Just for fun, I made list_str() recursively str() everything contained in the list.

Jeremy Cantrell
  • 26,392
  • 13
  • 55
  • 78
1

This should suffice.

When printing lists as well as other container classes, the contained elements will be printed using __repr__, because __repr__ is meant to be used for internal object representation. If we call: help(object.__repr__) it will tell us:

Help on wrapper_descriptor:

__repr__(self, /)
    Return repr(self).

And if we call help(repr) it will output:

Help on built-in function repr in module builtins:

repr(obj, /)
    Return the canonical string representation of the object.

    For many object types, including most builtins, eval(repr(obj)) == obj.

If __str__ is implemented for an object and __repr__ is not repr(obj) will output the default output, just like print(obj) when non of these are implemented.

So the only way is to implement __repr__ for your class. One possible way to do that is this:

class C:           
    def __str__(self):
        return str(f"{self.__class__.__name__} class str ")

C.__repr__=C.__str__       
ci = C()    


print(ci)       #C class str 
print(str(ci))  #C class str 
print(repr(ci)) #C class str 
prosti
  • 42,291
  • 14
  • 186
  • 151
1

Something like this?

a = [1, 2 ,3]
[str(x) for x in a]
# ['1', '2', '3']
WhatIsHeDoing
  • 541
  • 1
  • 6
  • 20
-2

The output you're getting is just the object's module name, class name, and then the memory address in hexadecimal as the the __repr__ function is not overridden.

__str__ is used for the string representation of an object when using print. But since you are printing a list of objects, and not iterating over the list to call the str method for each item it prints out the objects representation.

To have the __str__ function invoked you'd need to do something like this:

'my list is %s' % [str(x) for x in myList]

If you override the __repr__ function you can use the print method like you were before:

class cell:
    def __init__(self, id):
        self.id = id
    def __str__(self):
        return str(self.id) # Or whatever
    def __repr__(self):
        return str(self) # function invoked when you try and print the whole list.

myList = [cell(1), cell(2), cell(3)]
'my list is %s' % myList

Then you'll get "my list is [1, 2, 3]" as your output.

charliebeckwith
  • 1,449
  • 11
  • 29
  • This answer seems to be answering a completely unrelated question. Are you've sure you put it in the right place? – Blckknght Jan 25 '19 at 22:35
  • yes Blckknght this page that i wanted to give my answer had a link to this page from another post.so it guided me here and i answer here supposing that the guy who made the question will come here again and see my answer..sorry for the inconvienience!!! – panagiwtis koligas Jan 27 '19 at 15:58
  • If the other question was closed as a duplicate of this one, then it's sort of assumed that the *existing* answers here should already take care of the other question. If that's not the case, then you should be flagging to reopen that question, rather than posting an incomprehensible answer here, that will almost certainly be deleted. Now, it's possible you have something to say that isn't covered by one of the 8 other answers here, but you'd need to make your answer make sense in the context of this page, since it's this question you're answering. And don't post two identical answers! – Blckknght Jan 27 '19 at 17:51
  • 1
    Oh, though now that I look at it again, it seems @charliebeckwith has edited your post to be a completely different one, rather than posting their own answer, for some inexplicable reason. That's not normally how edits work... – Blckknght Jan 27 '19 at 17:56
  • @blckknght I started editting it before i realized how off the answer was. Completely inexplicable why i kept going. – charliebeckwith Jan 28 '19 at 05:30
  • @blckknght i'm still kinda laughing. At least my edit was on topic ? – charliebeckwith Jan 28 '19 at 05:36