Frage

Mit StringIO als String-Puffer ist langsamer als Liste als Puffer verwendet wird.

Wenn StringIO verwendet?

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

Ergebnisse:

16.7872819901
18.7160351276
War es hilfreich?

Lösung

Wenn Sie für die Geschwindigkeit messen, sollten Sie cStringIO verwenden.

Von der docs :

Das Modul cStringIO liefert ein Schnittstelle ähnlich zu dem der StringIO Modul. Die starke Nutzung von StringIO.StringIO Objekte vorgenommen werden können effizienter mit der Funktion StringIO () von diesem Modul statt.

Aber der Punkt von StringIO ist eine zu Datei-ähnliches Objekt , denn wenn etwas erwartet, dass diese und Sie wollen nicht unbedingt die Dateien verwenden.

Edit: Ich habe bemerkt, Sie from io import StringIO verwenden, so sind Sie wahrscheinlich auf Python> = 3 oder mindestens 2,6. Die separate StringIO und cStringIO sind in PY3 gegangen. Nicht sicher, welche Implementierung sie verwendet, um die io.StringIO bereitzustellen. Es gibt io.BytesIO auch.

Andere Tipps

Der Hauptvorteil von StringIO ist, dass es verwendet werden kann, wo eine Datei erwartet wurde. So können Sie zum Beispiel tun können (für Python 2):

import sys
import StringIO

out = StringIO.StringIO()
sys.stdout = out
print "hi, I'm going out"
sys.stdout = sys.__stdout__
print out.getvalue()

Nun, ich weiß nicht, ob ich nennen möchte, dass es als „Puffer“ verwendet wird, werden Sie nur eine Zeichenfolge, die eine 100-mal, in zwei komplizierte Weise multipliziert wird. Hier ist eine unkomplizierte Art und Weise:

def meth3(string):
    return string * 100

Wenn wir hinzufügen, dass auf Ihren Test:

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

Es stellt sich heraus viel schneller als Bonus zu sein:

21.0300650597
22.4869811535
0.811429977417

Wenn Sie eine Reihe von Zeichenketten erstellen möchten, und sie dann kommen, meth1 () ist der richtige Weg. Es gibt keinen Punkt, es zu StringIO in schriftlicher Form, die etwas ganz anderes, nämlich eine Zeichenfolge mit einer dateiähnliche Strom-Schnittstelle ist.

Ein weiterer Ansatz basiert auf Lennart Regebro Ansatz. Dies ist schneller als list-Methode (meth1)

def meth4(string):
    a = StringIO(string * 100)
    contents = a.getvalue()
    a.close()
    return contents

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())
    print(Timer("meth3(string)", "from __main__ import meth3, string").timeit())
    print(Timer("meth4(string)", "from __main__ import meth4, string").timeit())

Ergebnisse (Sek.):

meth1 = 7,731315963647944

meth2 = 9,609279402186985

meth3 = 0,26534052061106195

meth4 = 2,915035489152274

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top