Python string.join (lista) w tablicy obiektów zamiast w tablicy łańcuchów

291

W Pythonie mogę wykonać:

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

Czy jest jakiś prosty sposób, aby zrobić to samo, gdy mam listę obiektów?

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

Czy też muszę uciekać się do pętli for?

Mata
źródło

Odpowiedzi:

431

Zamiast tego możesz użyć zrozumienia listy lub wyrażenia generatora:

', '.join([str(x) for x in list])  # list comprehension
', '.join(str(x) for x in list)    # generator expression
Adam Rosenfield
źródło
3
lub wyrażenie generatora: ',' .join (str (x) dla x na liście)
dF.
1
jakiś pomysł, który z nich byłby szybszy?
gozzilli
Moje eksperymenty mówią, że zrozumienie listy może być o 60% szybsze na małych listach (eksperyment przebiega 10 ^ 6 razy na liście trzech obiektów). Jednak ich wydajność jest podobna na dużych listach (2. eksperyment przeprowadzany raz na liście 10 ^ 7 obiektów ()).
gozzilli
3
dla dobrego przyspieszenia o 30% (powyżej wyrażenia generatora powyżej) można użyć rzekomo mniej czytelnego mapwyrażenia (poniżej).
K3 --- rnc
2
Ta odpowiedź jest obiektywnie gorsza niż maprozwiązanie.
PascalVKooten
95

Wbudowany konstruktor ciągów automatycznie wywoła obj.__str__:

''.join(map(str,list))
Tryptyk
źródło
1
map () nie zmienia listy, jest równoważne z [str (o) dla o na liście]
dF.
11
+1: Mapa to dobre podejście; „zmiana listy” nie jest trafnym komentarzem.
S.Lott
2
(inny) +1 .. mapa nie jest mniej czytelna, wystarczy wiedzieć, co robi funkcja mapy
lapax 10.04.15
1
@Michael Niepoprawne. reducezostał usunięty, ponieważ zwykle pozostawiał ludzi w zgadywaniu, a zatem nie był „pythoniczny”. mapz drugiej strony nie stanowi problemu.
PascalVKooten
1
(inny) +1: pochodzący ze świata Perla jest to najczęstsza rzecz we wszechświecie: join ("sep", lista) - a wszystkie elementy listy są konwertowane na ich reprezentacje łańcuchowe. Naprawdę walczyłem o znalezienie rozwiązania w Pythonie.
Jason
2

innym rozwiązaniem jest zastąpienie operatora złączenia klasy str.

Zdefiniujmy nową klasę my_string w następujący sposób

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

To możesz zrobić

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

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

print comma.join(list)

i dostajesz

name,name,name

BTW, używając listy jako nazwy zmiennej, redefiniujesz klasę listy (słowo kluczowe)! Najlepiej użyj innej nazwy identyfikatora.

Mam nadzieję, że moja odpowiedź okaże się przydatna.

Nassim Seghir
źródło
1

Wiem, że to bardzo stary post, ale myślę, że to, co przeoczyłem, jest nadrzędne __repr__, więc to __repr__ = __str__, co jest akceptowaną odpowiedzią na to pytanie, jest oznaczone jako duplikat .

NotAnAmbiTurner
źródło