2011-01-19 28 views
40

Usar StringIO como un buffer de cadena es más lento que usar la lista como buffer.¿Cuándo se usa StringIO?

¿Cuándo se utiliza StringIO?

from io import StringIO 


def meth1(string): 
    a = [] 
    for i in range(100): 
     a.append(string) 
    return ''.join(a) 

def meth2(string): 
    a = StringIO() 
    for i in range(100): 
     a.write(string) 
    return a.getvalue() 


if __name__ == '__main__': 
    from timeit import Timer 
    string = "This is test string" 
    print(Timer("meth1(string)", "from __main__ import meth1, string").timeit()) 
    print(Timer("meth2(string)", "from __main__ import meth2, string").timeit()) 

Resultados:

16.7872819901 
18.7160351276 
+1

¿Quizás quiere decir "cuándo" en lugar de "dónde" arriba? –

Respuesta

23

Si se mide por la velocidad, se deben utilizar cStringIO.

Desde el docs:

El módulo cStringIO proporciona una interfaz similar a la del módulo StringIO . El uso intensivo de Los objetos StringIO.StringIO se pueden hacer más eficaces usando la función StringIO() de este módulo en su lugar .

Pero el punto de StringIO es ser un objeto de tipo fichero , por ejemplo cuando algo espera y que no quieren utilizar los archivos reales.

Edit: Me di cuenta de que usa from io import StringIO, por lo que probablemente esté en Python> = 3 o al menos 2.6. El StringIO y cStringIO por separado se han ido en Py3. No estoy seguro de qué implementación utilizaron para proporcionar el io.StringIO. Hay io.BytesIO también.

+0

Pruébalo con 'cStringIO'. Resultados: Lista: 17, cString: 33. – user225312

+3

io.StringIO es una implementación C, si existe en su plataforma. Si no, usa una implementación fallida de Python. La razón por la que es más lento es porque está haciendo algo para lo que no necesita StringIO en primer lugar. –

31

La principal ventaja de StringIO es que puede usarse donde se esperaba un archivo. Por lo que puede hacer por ejemplo:

import sys 
import StringIO 

out = StringIO.StringIO() 

sys.stdout = out 

print "hi, I'm going out" 

sys.stdout = sys.__stdout__ 

print out.getvalue() 
+0

¿Se puede usar con 'with' en python 2? De lo que veo aquí no: http://bugs.python.org/issue1286 –

+0

@Mr_and_Mrs_D see [http://bugs.python.org/issue1286#msg176512](http://bugs.python.org/issue1286 # msg176512) que indica que funcionará desde 2.5 hasta. ¿Qué más quieres, sangre en él? : D –

+0

@MarkLawrence: no, no volverá a leer el comentario que vinculó, tiene que rodar _su propio administrador de contexto –

17

Bueno, no sé si me gustaría llamar a que su uso como un "buffer", que se acaba de multiplicar una cadena de 100 veces, de dos formas complicadas . Aquí está una manera sencilla:

def meth3(string): 
    return string * 100 

Si añadimos que a su prueba:

if __name__ == '__main__': 

    from timeit import Timer 
    string = "This is test string" 
    # Make sure it all does the same: 
    assert(meth1(string) == meth3(string)) 
    assert(meth2(string) == meth3(string)) 
    print(Timer("meth1(string)", "from __main__ import meth1, string").timeit()) 
    print(Timer("meth2(string)", "from __main__ import meth2, string").timeit()) 
    print(Timer("meth3(string)", "from __main__ import meth3, string").timeit()) 

Resulta ser la forma más rápida como un bono:

21.0300650597 
22.4869811535 
0.811429977417 

Si desea crea un montón de cadenas y únete a ellas, meth1() es la forma correcta. No tiene sentido escribirlo en StringIO, que es algo completamente diferente, a saber, una cadena con una interfaz de flujo similar a un archivo.

Cuestiones relacionadas