class A:
def __init__(self, text):
self.text = text
def __repr__(self):
return self.text
def __str__(self):
return self.text
def __add__(self, other):
return str(self) + other
def __radd__(self, other):
return other + str(self)
I want that list of A
objects to be "joinable" with str.join().
Which special method should I implement to achieve this?
Of course, I can extract first a list of text then join it, but it's not what I want.
b = A('Hello')
c = A('World')
l = [b, c]
print b, c
print l
print b + ' ' + c
print ' '.join(l) # <- Error here
Hello World
[Hello, World]
Hello World
Traceback (most recent call last):
File "sandbox.py", line 24, in <module>
print ' '.join(l)
TypeError: sequence item 0: expected string, instance found
__str__
is only used if the user of your object wants to turn it into a string, and str.join
doesn't. You have to explicitly convert your objects to str
values before str.join
will use them.
(Could str.join
have been defined to implicitly call str
on each element in the iterable it receives as an argument? Sure. But it wasn't.)
One of the tenets of Python is "Explicit is better than implicit". If you want to str.join
to join the string representations of your objects, pass str
objects to join
.
print(' '.join(str(x) for x in l))
The only way join
will treat them as str
objects implicitly is if they are str
objects, which is to say if A
is a subclass of str
.
class A(str):
def __new__(cls, text):
obj = super().__new__(cls, text)
# Do whatever else you need to add to obj
return obj
l = [A('hello'), A('world')]
print(' '.join(l))
Beware of using inheritance where it isn't warranted, though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With