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

Або я повинен вдаватися до циклу for?

Відповіді:


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: карта - хороший підхід; "зміна списку" не є точним коментарем.
S.Lott

2
(інше) +1 .. карта не менш читабельна, просто потрібно знати, що робить функція карти
lapax

1
@Michael Неправильно. 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

BTW, використовуючи список як ім'я змінної, ви переосмислюєте клас списку (ключове слово)! Переважно використовувати інше ім'я ідентифікатора.

Сподіваюся, ви знайдете мою відповідь корисною.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.