Когда используется StringIO?
Использование StringIO в качестве строкового буфера медленнее, чем использование списка в качестве буфера.
Когда используется 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())
Результаты:
16.7872819901
18.7160351276
Ответы
Ответ 1
Если вы измеряете скорость, вы должны использовать cStringIO
.
Из docs:
Модуль cStringIO предоставляет интерфейс, аналогичный интерфейсу Модуль StringIO. Тяжелое использование Объекты StringIO.StringIO могут быть созданы более эффективно с помощью функции StringIO() из этого модуля.
Но точка StringIO должна быть файлоподобным объектом, потому что когда что-то ожидает, и вы не хотите использовать фактические файлы.
Изменить: Я заметил, что вы используете from io import StringIO
, поэтому вы, вероятно, находитесь на Python >= 3 или не менее 2.6. Отдельные StringIO и cStringIO ушли в Py3. Не знаю, какую реализацию они использовали для обеспечения io.StringIO. Существует также io.BytesIO
.
Ответ 2
Основное преимущество StringIO заключается в том, что его можно использовать там, где ожидался файл. Так вы можете сделать, например:
import sys
import StringIO
out = StringIO.StringIO()
sys.stdout = out
print "hi, I'm going out"
sys.stdout = sys.__stdout__
print out.getvalue()
Ответ 3
Ну, я не знаю, хочу ли я назвать это, используя его как "буфер", вы просто умножаете строку на 100 раз двумя сложными способами. Вот простой способ:
def meth3(string):
return string * 100
Если мы добавим это к вашему тесту:
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())
Он оказался быстрее в качестве бонуса:
21.0300650597
22.4869811535
0.811429977417
Если вы хотите создать связку строк, а затем присоедините их, метод meth1() будет правильным. Нет смысла записывать его в StringIO, что совершенно другое, а именно строка с файловым интерфейсом потока.