Python string.join (список) в массиве объектов, а не в массиве строк

291

В Python я могу сделать:

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

Есть ли простой способ сделать то же самое, когда у меня есть список объектов?

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

Или я должен прибегнуть к циклу?

Мат
источник

Ответы:

432

Вместо этого вы можете использовать понимание списка или выражение генератора:

', '.join([str(x) for x in list])  # list comprehension
', '.join(str(x) for x in list)    # generator expression
Адам Розенфилд
источник
3
или выражение генератора: ',' .join (str (x) для x в списке)
dF.
1
Есть идеи, кто из них будет быстрее?
gozzilli
Мои эксперименты говорят, что понимание списка может быть на 60% быстрее в небольших списках (эксперимент выполняется 10-6 раз для списка из трех объектов). Однако их производительность в больших списках одинакова (2-й эксперимент запускается один раз для списка из 10 ^ 7 объектов ()).
gozzilli
3
для хорошего ускорения на 30% (выше выражения генератора) можно использовать предположительно менее читаемое mapвыражение (ниже).
K3 --- RNC
2
Этот ответ объективно хуже mapрешения.
PascalVKooten
96

Встроенный строковый конструктор автоматически вызовет obj.__str__:

''.join(map(str,list))
Триптих
источник
1
map () не меняет список, это эквивалентно [str (o) для o в списке]
dF.
11
+1: карта - хороший подход; «изменение списка» не является точным комментарием.
С.Лотт
2
(другое) +1 .. карта не менее читабельна, просто нужно знать, что делает функция карты
lapax
1
@ Майкл Не правильно. reduceэто был тот, который был удален, потому что он обычно заставлял людей угадывать и, таким образом, не был "питоническим" mapс другой стороны это не проблема.
PascalVKooten
1
(другое) +1: из мира Perl это самая распространенная вещь во вселенной: join ("sep", list) - и все элементы списка преобразуются в свои строковые представления. Я действительно изо всех сил пытался найти решение в Python.
Джейсон
2

Другое решение - переопределить оператор соединения класса str.

Давайте определим новый класс my_string следующим образом

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

Тогда вы можете сделать

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

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

print comma.join(list)

и вы получите

name,name,name

Кстати, используя список в качестве имени переменной, вы переопределяете класс списка (ключевое слово)! Желательно использовать другое имя идентификатора.

Надеюсь, вы найдете мой ответ полезным.

Насим Сегир
источник
1

Я знаю, что это очень старый пост, но я думаю, что пропущено переопределяет __repr__, так что __repr__ = __str__, который является принятым ответом на этот вопрос, отмечен как дубликат .

NotAnAmbiTurner
источник