Joining a list of non-string python objects that implement __str__ method, using the .join function
Question:
I’ve already looked at this question on representing strings in Python but my question is slightly different. It is also different than the question How to concatenate (join) items in a list to a single string which was created after this question and applies to a list of strings and thus does not have any applicability to this question whatsoever (where the thrust of this question is specifically dealing with the challenge of non-string items).
Here’s the code:
>>> class WeirdThing(object):
... def __init__(self):
... self.me = time.time()
... def __str__(self):
... return "%s" % self.me
... def __repr__(self):
... return ";%s;" % self.me
...
>>> weird_list = [WeirdThing(), WeirdThing(), WeirdThing()]
>>> print weird_list
[;1302217717.89;, ;1302217717.89;, ;1302217717.89;]
>>> "n".join(weird_list)
Traceback (most recent call last):
File "<console>", line 1, in <module>
TypeError: sequence item 0: expected string, WeirdThing found
I realize that this works:
>>> "n".join(str(wi) for wi in weird_list)
'1302217717.89n1302217717.89n1302217717.89'
>>>
Still it would be nice to avoid doing that every time I want to join the objects together. Is it simply not possible?
Answers:
You have to stringify your objects before you can join them. This is because str.join
expects a series of strings, and you must give it a series of strings.
For the sake of less typing at the cost of readability, you can do "n".join(map(str, list_of_things)
.
You technically aren’t joining the list of python objects, just their string representation.
>>> reduce(lambda x,y: "%sn%s" % (x,y), weird_list)
'1302226564.83n1302226564.83n1302226564.83'
>>>
This works as well but doesn’t look any nicer:
>>> a = ""
>>> for x in weird_list:
... a+="%sn" % x
...
>>> print a
1302226564.83
1302226564.83
1302226564.83
>>>
There are probably no amazing way.
def strjoin(glue, iterable):
return glue.join(str(s) for s in iterable)
Would it work for you if you added an __add__
method? E.g.,
from operator import add
from random import randint
class WeirdThing(object):
def __init__(self,me=None):
self.me = me if me else chr(randint(97,122))
def __str__(self):
return "%s" % self.me
def __repr__(self):
return ";%s;" % self.me
def __add__(self,other):
new_me = add(str(self.me),str(other.me))
return WeirdThing(new_me)
weird_list = [WeirdThing(), WeirdThing(), WeirdThing()]
print weird_list
gives,
[;y;, ;v;, ;u;]
and this,
strange_thing = reduce(add,weird_list)
print strange_thing
gives,
yvu
“…it would be nice to avoid doing that every time…”
You want to avoid repeating that same code multiple times? Then use a function;:
def join_as_str(alist):
return "n".join(str(item) for item in alist)
I’ve already looked at this question on representing strings in Python but my question is slightly different. It is also different than the question How to concatenate (join) items in a list to a single string which was created after this question and applies to a list of strings and thus does not have any applicability to this question whatsoever (where the thrust of this question is specifically dealing with the challenge of non-string items).
Here’s the code:
>>> class WeirdThing(object):
... def __init__(self):
... self.me = time.time()
... def __str__(self):
... return "%s" % self.me
... def __repr__(self):
... return ";%s;" % self.me
...
>>> weird_list = [WeirdThing(), WeirdThing(), WeirdThing()]
>>> print weird_list
[;1302217717.89;, ;1302217717.89;, ;1302217717.89;]
>>> "n".join(weird_list)
Traceback (most recent call last):
File "<console>", line 1, in <module>
TypeError: sequence item 0: expected string, WeirdThing found
I realize that this works:
>>> "n".join(str(wi) for wi in weird_list)
'1302217717.89n1302217717.89n1302217717.89'
>>>
Still it would be nice to avoid doing that every time I want to join the objects together. Is it simply not possible?
You have to stringify your objects before you can join them. This is because str.join
expects a series of strings, and you must give it a series of strings.
For the sake of less typing at the cost of readability, you can do "n".join(map(str, list_of_things)
.
You technically aren’t joining the list of python objects, just their string representation.
>>> reduce(lambda x,y: "%sn%s" % (x,y), weird_list)
'1302226564.83n1302226564.83n1302226564.83'
>>>
This works as well but doesn’t look any nicer:
>>> a = ""
>>> for x in weird_list:
... a+="%sn" % x
...
>>> print a
1302226564.83
1302226564.83
1302226564.83
>>>
There are probably no amazing way.
def strjoin(glue, iterable):
return glue.join(str(s) for s in iterable)
Would it work for you if you added an __add__
method? E.g.,
from operator import add
from random import randint
class WeirdThing(object):
def __init__(self,me=None):
self.me = me if me else chr(randint(97,122))
def __str__(self):
return "%s" % self.me
def __repr__(self):
return ";%s;" % self.me
def __add__(self,other):
new_me = add(str(self.me),str(other.me))
return WeirdThing(new_me)
weird_list = [WeirdThing(), WeirdThing(), WeirdThing()]
print weird_list
gives,
[;y;, ;v;, ;u;]
and this,
strange_thing = reduce(add,weird_list)
print strange_thing
gives,
yvu
“…it would be nice to avoid doing that every time…”
You want to avoid repeating that same code multiple times? Then use a function;:
def join_as_str(alist):
return "n".join(str(item) for item in alist)