I have an object which defines some methods. I want to join a list or
an iterable of those objects like this:
new_string = "|".join(iterable_of_custom_objects)
What is the __magic__ function that needs to be implemented for
this case to work? I though that __str__ is sufficient but it doesn't seems to
work. Thanks in advance.
PC
You need to do the string conversion yourself; .join() doesn't do it
for you, due to strong typing. It only accepts iterables of strings:
new_string = "|".join(str(x) for x in iterable_of_custom_objects)
Cheers,
Chris
--
http://rebertia.com
Instead of join() here's a function that does something similar to
what the string join() method does. The first argument can be a list
of any type of objects and the second separator argument can likewise
be any type. The result is list of the various objects. (The example
usage just uses a list of string objects and separator to illustrate
what it does.)
def tween(seq, sep):
return reduce(lambda r,v: r+[sep,v], seq[1:], seq[:1])
lst = ['a','b','c','d','e']
print tween(lst, '|')
print ''.join(tween(lst, '|'))
Output:
['a', '|', 'b', '|', 'c', '|', 'd', '|', 'e']
a|b|c|d|e
It could be made a little more memory efficient by applying the
itertools module's islice() generator to the first 'seq' argument
passed to reduce():
def tween(seq, sep):
return reduce(lambda r,v: r+[sep,v], itertools.islice(seq,1,None),
seq[:1])
--
Martin
This version accepts any iterable, not just a list:
def tween(seq, sep):
it = iter(seq)
try:
first = it.next()
except StopIteration:
return []
return reduce(lambda r, v: r + [sep, v], it, [first])
A further efficiency improvement would be to do the list concatenation
in place to avoid generating O(n) intermediate copies:
def tween(seq, sep):
it = iter(seq)
try:
first = it.next()
except StopIteration:
return []
def add_sep(r, v):
r += [sep, v]
return r
return reduce(add_sep, it, [first])
You just have to implement __str__() python special method for your
"custom_objects".
Regards
Karim
> You just have to implement __str__() python special method for your
> "custom_objects".
> Regards
> Karim
>> Cheers,
>> Chris
>> --
>> http://rebertia.com
I already told in the first post that I've implemented __str__ function, but it doesn't
seems to be automatically called.
For instance, the following example won't work:
>>> class a:
def __init__(self, i):
self.i = i
def __str__(self):
return "magic_function_{}".format(self.i)
>>> t = a(0)
>>> str(t)
'magic_function_0'
>>> "".join([t])
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
"".join([t])
TypeError: sequence item 0: expected str instance, a found
--
Best regards,
Claudiu
The built-in str join() method just doesn't do the conversion to
string automatically -- instead it assume it has been given a sequence
of string. You can achieve the effect you want by modifying the
optimized version of my earlier post that @Ian Kelly submitted.
def join(seq, sep):
it = iter(seq)
sep = str(sep)
try:
first = it.next()
except StopIteration:
return []
def add_sep(r, v):
r += [sep, str(v)]
return r
return ''.join(reduce(add_sep, it, [str(first)]))
class A:
def __init__(self, i):
self.i = i
def __str__(self):
return "magic_function_{}".format(self.i)
lst = [A(0),A(1),A('b'),A(3)]
print repr( join(lst, '|') )
Output:
'magic_function_0|magic_function_1|magic_function_b|magic_function_3'
> I already told in the first post that I've implemented __str__ function,
> but it doesn't seems to be automatically called.
No, Python does not auto-coerce to strings (only between numbers).
You have to be explicit by calling str. Karim's statement "You just have
to implement __str__() python special method for your "custom_objects".
" means that str will then work.
> For instance, the following example won't work:
>
>>>> class a:
> def __init__(self, i):
> self.i = i
> def __str__(self):
> return "magic_function_{}".format(self.i)
>>>> t = a(0)
>>>> str(t)
> 'magic_function_0'
>>>> "".join([t])
print('\n'.join(str(ob) for ob in [a(0), a(1), a(None)]))
magic_function_0
magic_function_1
magic_function_None
--
Terry Jan Reedy
Thanks, I understand now.
> magic_function_0
> magic_function_1
> magic_function_None
--
Best regards,
Claudiu