Некоторые из нас, приверженцев Python, я полагаю, в основном Rigo и Hettinger, старались изо всех сил (на пути к 2.5, я полагаю) оптимизировать некоторые особые случаи, к сожалению, слишком распространенные s += something
упадок , утверждая, что было доказано, что новичкам никогда не удастся убедить, что ''.join
- верный путь, и ужасная медлительность +=
может дать Python дурную славу. Другие из нас не были такими горячими, потому что просто не могли оптимизировать каждое вхождение (или даже большинство из них) для достойной производительности; но мы не слишком горячо относились к этой проблеме, чтобы попытаться их активно заблокировать.
Я считаю, что эта тема доказывает, что мы должны были противостоять им более строго. Как и сейчас, они оптимизировали +=
в определенном трудно предсказуемом подмножестве случаев, где оно может быть, возможно, на 20% быстрее для конкретных глупых случаев, чем надлежащим образом (который все еще ''.join
) - просто идеальный способ заманить новичков в погоню за несущественными 20% -ными выигрышами, используя неверную идиому ... по цене, время от времени и от их POV на ровном месте, когда поражение с потерей производительности 200% (или больше) Так как нелинейное поведение все еще скрывается за пределами углов, которые Хеттингер и Риго намазывали и сажали цветы ;-) - тот, который имеет значение, тот, который сделает их несчастными. Это идет вразрез с «идеальным единственным очевидным способом сделать это» в Python, и мне кажется, что мы все вместе попали в ловушку для новичков - самый лучший вид тоже ... тех, кто не просто принимает то, что им говорят их "лучшие", но с любопытством иди и спрашивай и исследуй.
Ах, хорошо - я сдаюсь. OP, @mshsayem, продолжайте, используйте + = везде, наслаждайтесь своими неуместными ускорениями на 20% в тривиальных, крошечных, не относящихся к делу случаях, и вам лучше наслаждаться ими до предела - потому что однажды, когда вы не сможете этого увидеть Приходя в ВАЖНУЮ, БОЛЬШУЮ операцию, вы столкнетесь с ударом по животу встречным прицепом с замедлением на 200% (если вам не повезло, и это 2000% ;-). Просто помните: если вы когда-нибудь почувствуете, что «Питон ужасно медленный», ПОМНИТЕ, скорее всего, это одна из ваших любимых петель +=
, поворачивающихся и кусающих руку, которая его кормит.
Для остальных из нас - тех, кто понимает, что значит сказать Мы должны забыть о малой эффективности, скажем, в 97% случаев , я буду продолжать от души рекомендовать ''.join
, поэтому мы все можем спать в полном спокойствии и ЗНАТЬ, что суперлинейное замедление не вызовет нас, когда мы меньше всего ожидаем и меньше всего можем себе позволить. Но для вас, Армин Риго и Рэймонд Хеттингер (последние двое, мои дорогие личные друзья, кстати, не просто соавторы ;-) - пусть ваш +=
будет гладким, а ваши биг-о никогда не хуже N! -)
Итак, для всех остальных, вот более значимый и интересный набор измерений:
$ python -mtimeit -s'r=[str(x)*99 for x in xrange(100,1000)]' 's="".join(r)'
1000 loops, best of 3: 319 usec per loop
900 строк по 297 символов в каждой, непосредственное присоединение к списку, конечно, происходит быстрее, но ОП боится необходимости добавлять дополнения до этого. Но:
$ python -mtimeit -s'r=[str(x)*99 for x in xrange(100,1000)]' 's=""' 'for x in r: s+=x'
1000 loops, best of 3: 779 usec per loop
$ python -mtimeit -s'r=[str(x)*99 for x in xrange(100,1000)]' 'z=[]' 'for x in r: z.append(x)' '"".join(z)'
1000 loops, best of 3: 538 usec per loop
... с полусущественным объемом данных (несколько сотен килобайт в КБ - с измеряемой долей миллисекунды в разные стороны), даже старый добрый .append
уже превосходен. Кроме того, его легко и просто оптимизировать:
$ python -mtimeit -s'r=[str(x)*99 for x in xrange(100,1000)]' 'z=[]; zap=z.append' 'for x in r: zap(x)' '"".join(z)'
1000 loops, best of 3: 438 usec per loop
брить еще десятые доли миллисекунды в течение среднего времени цикла. Все (по крайней мере, все, кто полностью помешан на высокой производительности), очевидно, знают, что HOISTING (извлекающий из внутреннего цикла повторяющиеся вычисления, которые в противном случае выполнялись бы снова и снова) - это ключевой прием в оптимизации - Python не поднимает ваш запрос от вашего имени. так что вы должны делать свой подъем в тех редких случаях, когда важна каждая микросекунда.