2010-03-10 13 views
70

¿Hay alguna clase de cadena en Python como StringBuilder en C#?clase de cadena Python como StringBuilder en C#?

+1

Esto es un duplicado de [Python equivalente a Java StringBuffer] (https://stackoverflow.com/questions/19926089/python-equivalent-of-java-stringbuffer). ** PRECAUCIÓN: las respuestas aquí están desactualizadas y, de hecho, se han vuelto engañosas. ** Ver [esa otra pregunta] (https://stackoverflow.com/questions/19926089/python-equivalent-of-java- stringbuffer) para respuestas que son más relevantes para las versiones modernas de Python (ciertamente 2.7 y superiores). –

Respuesta

58

no existe una correlación uno a uno. Para un artículo muy bueno consulte Efficient String Concatenation in Python:

La construcción de cadenas largas en el lenguaje de programación Python veces puede resultado en el código de ejecución muy lenta. En este artículo investigo el rendimiento computacional de varios métodos de concatenación de cadenas .

+14

Tenga en cuenta que este artículo fue escrito basado en Python 2.2. Es probable que las pruebas salgan de forma algo diferente en una versión moderna de Python (CPython normalmente optimiza la concatenación, pero no desea depender de esto en un código importante) y una expresión del generador donde usa una lista de comprensión sería digna de consideración . –

+3

Sería bueno incluir algunos aspectos destacados en ese artículo, al menos un par de las implementaciones (para evitar problemas de enlace). – jpmc26

+3

Método 1: resultString + = appendString es el más rápido de acuerdo con las pruebas de @ Antoine-tran por debajo de – Justas

4

puede probar o StringIOcStringIO

+2

FYI Ninguno de esos enlaces está funcionando ahora –

+0

¡Están trabajando ahora! –

12

Python tiene varias cosas que cumplen los propósitos similares:

  • Una forma común para construir grandes cadenas de piezas es hacer crecer una lista de cadenas y unirse a ella cuando haya terminado. Esta es una expresión idiomática de Python frecuentemente utilizada.
    • Para construir cadenas que incorporen datos con el formateo, usted haría el formateo por separado.
  • Para la inserción y eliminación a nivel de carácter, mantendría una lista de cadenas de longitud-una. (Para hacer esto desde una cadena, que se dice list(your_string). También es posible usar un UserString.MutableString para esto.
  • (c)StringIO.StringIO es útil para cosas que de otra manera tomaría un archivo, pero no tanto para la construcción en general cadena.
23

He usado el código de Oliver Crow (enlace proporcionado por Andrew Hare) y lo he adaptado un poco para adaptar Python 2.7.3. (Usando el paquete timeit). Corrí en mi computadora personal, Lenovo T61, 6GB RAM, Debian GNU/Linux 6.0.6 (squeeze).

Aquí está el resultado de 10.000 iteraciones:

 
method1: 0.0538418292999 secs 
process size 4800 kb 
method2: 0.22602891922 secs 
process size 4960 kb 
method3: 0.0605459213257 secs 
process size 4980 kb 
method4: 0.0544030666351 secs 
process size 5536 kb 
method5: 0.0551080703735 secs 
process size 5272 kb 
method6: 0.0542731285095 secs 
process size 5512 kb 

y 5.000.000 iteraciones (método 2 se ignoró porque corrió alargó lentamente, como siempre):

 
method1: 5.88603997231 secs 
process size 37976 kb 
method3: 8.40748500824 secs 
process size 38024 kb 
method4: 7.96380496025 secs 
process size 321968 kb 
method5: 8.03666186333 secs 
process size 71720 kb 
method6: 6.68192911148 secs 
process size 38240 kb 

Es bastante obvio que los chicos Python han hecho muy buen trabajo para optimizar la concatenación de cadenas, y como Hoare dijo: "optimización prematura es la raíz de todo mal" :-)

+1

Aparentemente Hoare no acepta que: http://hans.gerwitz.com/2004/08/12/premature-optimization-is-the-root-of-all-evil.html –

+2

No es una optimización prematura para evitar frágiles, optimizaciones dependientes del intérprete. Si alguna vez quiere exportar a PyPy o arriesgarse a [uno de los muchos casos de fallas sutiles] (http://stackoverflow.com/questions/24040198/cpython-string-addition-optimisation-failure-case) para la optimización, haga cosas de la manera correcta. – Veedrac

+0

Parece que el método 1 es más fácil de optimizar para el compilador. – mbomb007

8

5 Utilizando el método de arriba (el archivo Pseudo) podemos obtener muy buenos Potencia y flexibilidad

from cStringIO import StringIO 

class StringBuilder: 
    _file_str = None 

    def __init__(self): 
     self._file_str = StringIO() 

    def Append(self, str): 
     self._file_str.write(str) 

    def __str__(self): 
     return self._file_str.getvalue() 

ahora usarlo

sb = StringBuilder() 

sb.Append("Hello\n") 
sb.Append("World") 

print sb 
-1

Si estás aquí buscando un método rápido concatenación de cadenas en Python, entonces usted no necesita una clase especial StringBuilder. La concatenación simple funciona igual de bien sin la penalización de rendimiento que se ve en C#.

resultString = "" 

resultString += "Append 1" 
resultString += "Append 2" 

Ver Antoine-tran's answer de los resultados de rendimiento

5

Basándose en las optimizaciones del compilador es frágil. Los puntos de referencia vinculados en la respuesta aceptada y los números dados por Antoine-tran no son confiables. Andrew Hare comete el error de incluir una llamada al repr en sus métodos. Eso ralentiza todos los métodos por igual pero oscurece la penalidad real al construir la cuerda.

Use join. Es muy rápido y más robusto.

$ ipython3 
Python 3.5.1 (default, Mar 2 2016, 03:38:02) 
IPython 4.1.2 -- An enhanced Interactive Python. 

In [1]: values = [str(num) for num in range(int(1e3))] 

In [2]: %%timeit 
    ...: ''.join(values) 
    ...: 
100000 loops, best of 3: 7.37 µs per loop 

In [3]: %%timeit 
    ...: result = '' 
    ...: for value in values: 
    ...:  result += value 
    ...: 
10000 loops, best of 3: 82.8 µs per loop 

In [4]: import io 

In [5]: %%timeit 
    ...: writer = io.StringIO() 
    ...: for value in values: 
    ...:  writer.write(value) 
    ...: writer.getvalue() 
    ...: 
10000 loops, best of 3: 81.8 µs per loop 
0

No hay análogo explícita - Creo que se espera que utilice concatenaciones de cadenas (probablemente optimizados como se dijo antes) o clase de terceros (i duda de que son mucho más eficiente - listas en Python son dinámicos -tipo por lo que no funciona rápido char [] para el búfer como supongo). Las clases similares a Stringbuilder no son una optimización prematura debido a la característica innata de cadenas en muchos idiomas (inmutabilidad), que permite muchas optimizaciones (por ejemplo, hacer referencia al mismo búfer para segmentos/subcadenas). Las clases Stringbuilder/stringbuffer/stringstream funcionan mucho más rápido que la concatenación de cadenas (produciendo muchos pequeños objetos temporales que aún necesitan asignaciones y recolección de basura) e incluso formatean herramientas tipo printf, sin necesidad de interpretar una sobrecarga de patrón de formateo que consume bastante para muchas llamadas de formato.