[Python] Оптимизация соединения множества строк
От: Critical Error ICQ: 123736611
Дата: 19.07.10 05:45
Оценка:
Понадобилось мне как-то сделать из таблички в питоне html. Табличка объемная вопрос оптимизации важен.

А тут на хабре статья забавная появилась. Там в комментах рекомендуют использовать ''.join(list) вместо str += str.

Решил последовать совету и переписал свою функцию. А теперь самое интересное: соединение юникодных строк происходит действительно раз в 10 быстрее, но вот для ansi-строк проигрывает. Хотелось бы узнать почему так?

Вот полный код теста:

from time import time

printHeader = """
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251"/></head>
<body><h1>%s</h1><table cellspacing="0" cellpadding="0">
"""

s1 = (u'Тест', u'Еще тест')*8
s1 = [i.encode('cp1251') for i in s1]
s2 = [s1]*500

def table2html1(src, s1, printHeader):
    s = printHeader % 'dfgsdfgsdfg'
    s += '<tr>'
    for col in s1:
        s += '<td>%s&nbsp</td>'%col
    s += '</tr>\n'

    for row in src:
        s += '<tr>'
        for col in row:
            s += '<td>%s&nbsp</td>'%col
        s += '</tr>\n'
    
    s += "</table></body></html>"            
    return s

def table2html2(src, s1, printHeader):
    mkRow = lambda row: ''.join(sum((('<td>', col, '&nbsp</td>') for col in row), ()))
    mkDoc = lambda doc: ''.join(sum((('<tr>', mkRow(row), '</tr>\n') for row in doc), ()))
    return ''.join((printHeader % 'dfgsdfgsdfg', mkDoc([s1]), mkDoc(src), '</table></body></html>'))

from cStringIO import StringIO

def table2html3(src, s1, printHeader):
    s = StringIO()
    s.write(printHeader % 'dfgsdfgsdfg')

    def mkDoc(doc):
        for row in doc:
            s.write('<tr>')
            for col in row:
                s.write('<td>')
                s.write(col)
                s.write('&nbsp</td>')
            s.write('</tr>\n')
            
    mkDoc([s1])
    mkDoc(src)
    
    s.write("</table></body></html>")
    return s.getvalue()

t = time()
result1 = table2html1(s2, s1, printHeader)
print time()-t

t = time()
result2 = table2html2(s2, s1, printHeader)
print time()-t

t = time()
result3 = table2html3(s2, s1, printHeader)
print time()-t

with open('join1.html', 'wb') as fd:
    fd.write(result1)

with open('join2.html', 'wb') as fd:
    fd.write(result2)
    
with open('join3.html', 'wb') as fd:
    fd.write(result3)


Тут еще одна версия есть с использованием cStringIO — table2html3.

Результаты:
0.00999999046326
0.0150001049042
0.0190000534058


Если закоментировать вверху s1 = [i.encode('cp1251') for i in s1]:
0.648000001907
0.018000125885
Traceback (most recent call last): # cStringIO с юникодом не работает, нужно оставить StringIO, но он медленнее.


Или я что-то упустил?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.