Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to str.join() in list of objects

Tags:

python

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
like image 972
Ghilas BELHADJ Avatar asked Dec 19 '22 03:12

Ghilas BELHADJ


1 Answers

__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.

like image 56
chepner Avatar answered Dec 20 '22 19:12

chepner