[Python-3000] Proposal to add __str__ method to iterables.

Carl Johnson carl at carlsensei.com
Wed May 28 05:48:41 CEST 2008


Proposal to add __str__ method to iterables:

Proposed behavior of the __str__ method for iterables is that it  
returns the result of "".join(str(i) for i in self).

Justification:

Notice this difference in the behavior of filter* and a list  
comprehension:

 >>> filter(lambda c: c!="a", "abracadbra")
'brcdbr'
 >>> [c for c in "abracadbra" if c != "a"]
['b', 'r', 'c', 'd', 'b', 'r']

*This is the pre-3.0 filter's behavior. Post-3.0, "filter" is really  
ifilter.

In order to replicate the behavior of filter with a comprehension, the  
return type must be the same as the input type:

 >>> def my_filter(cond, it):
...     return type(it)(i for i in it if cond(i))

Thus, we get the same results using the old style filter and my_filter:

 >>> filter(lambda c: c!="a", (1,2))
(1, 2)
 >>> my_filter(lambda c: c!="a", (1,2))
(1, 2)
 >>> filter(lambda c: c!="a", [1,2])
[1, 2]
 >>> my_filter(lambda c: c!="a", [1,2])
[1, 2]

But not in every case!

 >>> filter(lambda c: c!="a", "abracadbra")
'brcdbr'
 >>> my_filter(lambda c: c!="a", "abracadbra")
'<generator object at 0x27c2300>'

Why does my_filter return a string saying "<generator object at  
blah>"? Because generator objects have no __str__ method, so  
str(gen_obj) returns gen_obj.__repr__().

So, my proposal is to make strings act like the other members of the  
iterable family by adding an __str__ method to them, which does a  
"".join on the str of its members.

- - - -

Potential downside #1: Don't try to print an infinite object, like  
itertools.count().

Other potential downside #2: This makes "".join(l) obsolete.

Regarding #1: Do a repr instead.

Regarding #2: I don't consider that to be a bad thing actually. I  
think doing "".join is very unnatural for people new to Python, and I  
think that even as people who are used to Python, I think we should  
admit that it's a little weird to join list members in that way.

In terms of actual implementation, this could also be done by having  
the str class look for a __str__ method then a __iter__ method and  
only then use __repr__ as the final fallback instead of falling back  
to __repr__ as is done now. That might be easier than adding __str__  
methods to all iterables.

- - - -

Incidentally, I think the idea that str(["1", "2"]) should return "[1,  
2]" is a terrible idea. Where's the use case for that? When would you  
ever need to print that? It should return "12", which actually does  
have a use case as the replacement for "".join(["1", "2"]).


More information about the Python-3000 mailing list