Python string.join (lista) en la matriz de objetos en lugar de la matriz de cadenas

291

En Python, puedo hacer:

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

¿Hay alguna manera fácil de hacer lo mismo cuando tengo una lista de objetos?

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

¿O tengo que recurrir a un bucle for?

Estera
fuente

Respuestas:

432

En su lugar, podría usar una comprensión de lista o una expresión generadora:

', '.join([str(x) for x in list])  # list comprehension
', '.join(str(x) for x in list)    # generator expression
Adam Rosenfield
fuente
3
o una expresión generadora: ',' .join (str (x) para x en la lista)
dF.
1
alguna idea sobre cuál de ellos sería más rápido?
gozzilli
Mis experimentos dicen que la comprensión de la lista puede ser un 60% más rápida en listas pequeñas (el experimento se ejecuta 10 ^ 6 veces en una lista de tres objetos). Sin embargo, su rendimiento es similar en las grandes listas (segundo experimento realizado una vez en una lista de 10 ^ 7 objetos ()).
gozzilli
3
para un buen 30% de aceleración (sobre la expresión del generador arriba), se puede usar la mapexpresión supuestamente menos legible (abajo).
K3 --- rnc
2
Esta respuesta es objetivamente peor que la mapsolución.
PascalVKooten
96

El constructor de cadenas incorporado llamará automáticamente obj.__str__:

''.join(map(str,list))
Tríptico
fuente
1
map () no cambia la lista, es equivalente a [str (o) para o en la lista]
dF.
11
+1: el mapa es un buen enfoque; "cambiar la lista" no es un comentario exacto.
S.Lott
2
(otro) +1 ... el mapa no es menos legible, solo necesito saber qué hace la función del mapa
lapax
1
@Michael No es correcto. reducefue el que se eliminó, porque generalmente dejaba a la gente adivinando y, por lo tanto, no era "pitónico". mapPor otro lado, no es un problema.
PascalVKooten
1
(otro) +1: viniendo del mundo de Perl, esto es lo más común en el universo: unirse ("sep", lista) - y todos los elementos de la lista se convierten en sus representaciones de cadena. Realmente he estado luchando por encontrar una solución en Python.
Jason
2

Otra solución es anular el operador de unión de la clase str.

Definamos una nueva clase my_string de la siguiente manera

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

Entonces puedes hacer

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

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

print comma.join(list)

y obtienes

name,name,name

Por cierto, al usar la lista como nombre de variable, está redefiniendo la clase de lista (palabra clave) Preferiblemente use otro nombre de identificador.

Espero que mi respuesta sea útil.

Nassim Seghir
fuente
1

Sé que esta es una publicación súper antigua, pero creo que lo que se pierde es anular __repr__, por lo que esa __repr__ = __str__es la respuesta aceptada de esta pregunta marcada como duplicada .

NotAnAmbiTurner
fuente