Python string.join (list) sur un tableau d'objets plutôt que sur un tableau de chaînes

291

En Python, je peux faire:

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

Existe-t-il un moyen simple de faire de même lorsque j'ai une liste d'objets?

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

Ou dois-je recourir à une boucle for?

Tapis
la source

Réponses:

432

Vous pouvez utiliser une compréhension de liste ou une expression de générateur à la place:

', '.join([str(x) for x in list])  # list comprehension
', '.join(str(x) for x in list)    # generator expression
Adam Rosenfield
la source
3
ou une expression de générateur: ',' .join (str (x) pour x dans la liste)
dF.
1
une idée sur lequel d'entre eux serait plus rapide?
gozzilli
Mes expériences indiquent que la compréhension de la liste peut être 60% plus rapide sur de petites listes (expérience exécutée 10 ^ 6 fois sur une liste de trois objets). Cependant, leurs performances sont similaires sur de grandes listes (2e expérience exécutée une fois sur une liste de 10 ^ 7 objets ()).
gozzilli
3
pour une bonne accélération de 30% (au-dessus de l'expression du générateur ci-dessus), on peut utiliser l' mapexpression soi-disant moins lisible (ci-dessous).
K3 --- rnc
2
Cette réponse est objectivement pire que la mapsolution.
PascalVKooten
96

Le constructeur de chaîne intégré appellera automatiquement obj.__str__:

''.join(map(str,list))
Triptyque
la source
1
map () ne change pas la liste, c'est équivalent à [str (o) pour o dans la liste]
dF.
11
+1: la carte est une bonne approche; "changer la liste" n'est pas un commentaire précis.
S.Lott
2
(un autre) +1 .. la carte n'est pas moins lisible, il suffit de savoir ce que fait la fonction de carte
lapax
1
@Michael Pas correct. reduceétait celle qui avait été supprimée, car elle laissait généralement les gens deviner et n'était donc pas "pythonique". mapd'autre part n'est pas un problème.
PascalVKooten du
1
(un autre) +1: venant du monde Perl, c'est la chose la plus courante dans l'univers: join ("sep", list) - et tous les éléments de list sont convertis en leurs représentations de chaînes. J'ai vraiment du mal à trouver une solution en python.
Jason
2

une autre solution consiste à remplacer l'opérateur de jointure de la classe str.

Définissons une nouvelle classe my_string comme suit

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

Ensuite, vous pouvez faire

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

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

print comma.join(list)

et vous obtenez

name,name,name

BTW, en utilisant list comme nom de variable, vous redéfinissez la classe list (mot-clé)! Utilisez de préférence un autre nom d'identifiant.

J'espère que vous trouverez ma réponse utile.

Nassim Seghir
la source
1

Je sais que c'est un super vieux post, mais je pense que ce qui manque est primordial __repr__, de sorte que __repr__ = __str__, qui est la réponse acceptée de cette question marquée en double .

NotAnAmbiTurner
la source