Python string.join (Liste) auf Objektarray anstatt auf String-Array

291

In Python kann ich Folgendes tun:

>>> list = ['a', 'b', 'c']
>>> ', '.join(list)
'a, b, c'

Gibt es eine einfache Möglichkeit, dasselbe zu tun, wenn ich eine Liste von Objekten habe?

>>> class Obj:
...     def __str__(self):
...         return 'name'
...
>>> list = [Obj(), Obj(), Obj()]
>>> ', '.join(list)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: sequence item 0: expected string, instance found

Oder muss ich auf eine for-Schleife zurückgreifen?

Matte
quelle

Antworten:

432

Sie können stattdessen ein Listenverständnis oder einen Generatorausdruck verwenden:

', '.join([str(x) for x in list])  # list comprehension
', '.join(str(x) for x in list)    # generator expression
Adam Rosenfield
quelle
3
oder ein Generatorausdruck: ',' .join (str (x) für x in Liste)
dF.
1
Irgendeine Idee, welcher von ihnen schneller sein würde?
Gozzilli
Meine Experimente besagen, dass das Listenverständnis bei kleinen Listen gut 60% schneller sein kann (Experiment wird 10 ^ 6 Mal mit einer Liste von drei Objekten ausgeführt). Ihre Leistung ist jedoch auf großen Listen ähnlich (2. Experiment einmal auf einer 10 ^ 7-Objektliste () ausgeführt).
Gozzilli
3
Für eine Beschleunigung von gut 30% (über dem Generatorausdruck oben) kann man den vermeintlich weniger lesbaren mapAusdruck (unten) verwenden.
K3 --- rnc
2
Diese Antwort ist objektiv schlechter als die mapLösung.
PascalVKooten
96

Der integrierte String-Konstruktor ruft automatisch auf obj.__str__:

''.join(map(str,list))
Triptychon
quelle
1
map () ändert die Liste nicht, es entspricht [str (o) für o in der Liste]
dF.
11
+1: Karte ist ein guter Ansatz; "Ändern der Liste" ist kein genauer Kommentar.
S.Lott
2
(eine andere) +1 .. Karte ist nicht weniger lesbar, muss nur wissen, was die Kartenfunktion tut
Lapax
1
@ Michael Nicht korrekt. reducewar derjenige, der entfernt wurde, weil es normalerweise Leute erraten ließ und somit nicht "pythonisch" war. mapauf der anderen Seite ist kein Problem.
PascalVKooten
1
(eine andere) +1: Aus der Perl-Welt kommend ist dies die häufigste Sache im Universum: join ("sep", list) - und alle Elemente der Liste werden in ihre String-Darstellungen konvertiert. Ich habe wirklich Mühe gehabt, eine Lösung in Python zu finden.
Jason
2

Eine andere Lösung besteht darin, den Join-Operator der Klasse str zu überschreiben.

Definieren wir eine neue Klasse my_string wie folgt

class my_string(str):
    def join(self, l):
        l_tmp = [str(x) for x in l]
        return super(my_string, self).join(l_tmp)

Dann können Sie tun

class Obj:
    def __str__(self):
        return 'name'

list = [Obj(), Obj(), Obj()]
comma = my_string(',')

print comma.join(list)

und du bekommst

name,name,name

Übrigens, indem Sie list als Variablennamen verwenden, definieren Sie die Listenklasse (Schlüsselwort) neu! Verwenden Sie vorzugsweise einen anderen Bezeichnernamen.

Ich hoffe, Sie finden meine Antwort hilfreich.

Nassim Seghir
quelle
1

Ich weiß, dass dies ein super alter Beitrag ist, aber ich denke, was übersehen wird __repr__, ist überschreibend , so dass __repr__ = __str__dies die akzeptierte Antwort auf diese Frage ist, die als doppelt markiert ist .

NotAnAmbiTurner
quelle