¿Debo evitar convertir a una cadena si un valor ya es una cadena?

A veces tienes que usar la comprensión de la lista para convertir todo en una cadena, incluidas las cadenas.

b = [str(a) for a in l] 

Pero tengo que hacer

 b = [a if type(a)==str else str(a) for a in l] 

Me preguntaba si str en una cadena está lo suficientemente optimizada para no crear otra copia de la cadena.

Yo he tratado:

 >>> x="aaaaaa" >>> str(x) is x True 

pero eso puede ser porque Python puede almacenar cadenas en caché, y las reutiliza. ¿Pero está garantizado ese comportamiento para cualquier valor de una cadena?

Probar si un objeto ya es una cadena es más lento que simplemente convertirse siempre en una cadena.

Esto se debe a que el método str() también realiza la misma prueba (ya que el objeto ya es una cadena). Usted está a) haciendo el doble del trabajo yb) su prueba es más lenta para iniciar.

Nota: para Python 2, el uso de str() en objetos unicode incluye una encoding implícita a ASCII, y esto puede fallar. Es posible que aún tenga que manejar casos especiales de tales objetos. En Python 3, no hay necesidad de preocuparse por ese caso de borde.

Como hay alguna discusión alrededor de esto:

  • isinstance(s, str) tiene un significado diferente cuando s puede ser una subclase de str . Como las subclases son tratadas exactamente como cualquier otro tipo de objeto por str() (se llama __str__ o __repr__ en el objeto), esta diferencia es importante aquí.
  • Debe usar el type(s) is str para verificaciones de tipo exactas Los tipos son singletons, aprovecha esto, es más rápido:

     >>> import timeit >>> timeit.timeit("type(s) is str", "s = ''") 0.10074466899823165 >>> timeit.timeit("type(s) == str", "s = ''") 0.1110201120027341 
  • Usar s if type(s) is str else str(s) es significativamente más lento para el caso sin cadena :

     >>> import timeit >>> timeit.timeit("str(s)", "s = None") 0.1823573520014179 >>> timeit.timeit("s if type(s) is str else str(s)", "s = None") 0.29589492800005246 >>> timeit.timeit("str(s)", "s = ''") 0.11716728399915155 >>> timeit.timeit("s if type(s) is str else str(s)", "s = ''") 0.12032335300318664 

    (Los tiempos para los casos s = '' están muy cerca y se mantienen intercambiando lugares).

Todos los tiempos en esta publicación se realizaron en Python 3.6.0 en una Macbook Pro 15 “(mediados de 2015), OS X 10.12.3.