kb
24.08.2011 17:31 Gajim
Новости с фронта "asd" += "dsa". Как известно, в CPython += быстрый, а в PyPy — медленный. Объясняется это тем, что в CPython сделан некоторый хак для ускорения (в будущем, возможно, что-то появится и в PyPy). Но суть в том, что "собирать" строку через += в питоне в принципе неправильно, потому что каждый += создает новую строку. (по иронии, хак в CPython запилил один из разработчиков PyPy).
Таким образом, собирайте вашу строку при помощи u"".join([список_строк]) и не выпендривайтесь. Ну я лично еще сделал некоторый класс UnicodeBucket, но наверное проще не выпендриваться и таки u"".join() использывать
это ты выпендриваешься, а не мы. += это просто, понятно и быстро
это ты не выпендривайся. += даже в CPython тормознутое говно
ну так естественно, по сравнению с StringIO да. А через join — это пиздец
почему?
потому что ты создаёшь ещё один список и выглядит это как последнее говно.
как раз через join() — правильный способ. Потому что ты, по сути, собираешь строку из кусков. То есть у тебя список кусков и тебе их надо склеить. Семантически join() — верный способ. А cStringIO — это file-like объект. Создавать file-like объект для сборки строки — семантически неверно нихуя.
ret_val = ["initial value"], ret_val.append("moar moar moar"), u"".join(ret_val). Нормально выглядит. Уж в сравнении с cStringIO так точно.
или ret_val = "initial value", ret_val += "moar moar moar". Сравни
ну вот для таких как ты я и написал UnicodeBucket. На скриншот глянь. Будет ret_val = UnicodeBucket("initial value"), ret_val += "moar moar moar". Э?
а как потом получаешь строку из ret_val?
сама получится когда unicode() над ней делать будут (или печатать или что там)
короче лениво будет сидеть и ждать, пока не потребуют преобразования в строку
не нужно ибо совсем не очевидно, хотя оптимизирует ровно одну строку
щито? что тебе не очевидно? Почему одну строку?
не очевидно будет тому человеку, который откроет твой код, добредёт до огромного цикла, увидит, что ты к строке прибавляешь строку и воткнёт что-нибудь рядом для этой строки. А оно херню сделает — выдаст какой-то UnicodeBucket и давай ищи, что это и откуда
какую херню сделает? Что воткнет?
да что угодно. Не вижу смысла плодить абстракции ради экономии одной строчки.
да какая нахрен одна строчка? Ты не видишь, что оно медленнее в 200 раз??
ты сделал абстракцию над [] + join. Всего-то
и это только на 30000
нет. Я сделал абстракцию над "собиранием строки" для возврата, это очень частая операция много где. А реализация может быть через [] + join, может через cStringIO. Но правильнее через [] + join, да.
так вот я и пришел к тому, что буду использовать [] + join на прямую, но для тех, кто считает "фууу, некрасиво" напиал UnicodeBucket (точнее, для себя писал, а потом понял, что мне не лень [] + join делать)
и зачем тебе разные реализации?
не понял, какие разные реализации?
никому не лень, если оно действительно надо
на join и на stringio
незачем. Ты просто сказал, что абстракция над [] + join. А я говорю, что это абстракция над совершенно другим.
а [] является лишь реализацией этой абстракции, и возможна и другая реализация, через cStringIO, но абстракция все равно той же останется
просто нельзя говорить "это абстракция над тем-то и тем-то", рассказывая реализацию этой абстракции. Абстракция для того и нужна, чтобы объяснять что она делает, а не как.
я не собираюсь пользоваться непонятно чем, мне нужно знать, что внутри твоей абстракции. И, как выяснилось, это просто обёртка над методами
А ЧЕМ ЭТО ЕЩЕ МОЖЕТ БЫТЬ? В программировании всё — просто обертка над методами.
неправда. Бывают не просто обёртки над методами, а обёртки, делающие что-то новое.
например?
например += не содержит одну строчку "self.lst.append", а __str__ не содержит одну строчку "return ''.join(self.lst)". А содержит две или три строчки.
Тебе расписать на две или три строчки или что?
зачем расписывать на три строчки то, что прекрасно и без препятствий влазит в одну? Просто незачем плодить лишние сущности, которые только путают всех, кто читает твой код
пойми. Есть проблема: нельзя пользоваться += для сборки строки из большого количества кусков. Точка. Нельзя и всё, потому что тормоз, потому что на каждый += создается новая строка. Надо построить некоторую абстракцию для "сборки строки в одну". Вот я её и написал. Хочешь — пиши [] + join, хочешь — используй эту абстракцию. И там и там ты будешь прав. Но во втором случае только потому, что абстракция не присутствует в стандартном питоне и накладно её городить каждый раз.
man stringbuilder
в точку
вот и буду использовать [] + join, чтобы не было лишних вызовов
может сразу на ассамблере будешь писать?
нет, не буду. Буду использовать абстракции только там, где они нужны
Нужно паять программы из транзисторов и конденсаторов, а остальное — понты и не нужно.
кстати, оказывается твой класс уже давно существует. from UserString import MutableString
по поводу однострочных абстракций — вот тебе хороший пример http://habrahabr.ru/blogs/cpp/126227/
зато pythonic
как видишь, их абстракции состоят не из одной строчки, а из многих
нужно строить последовательности из расколотых дров, заставлять их двигаться при помощи силы ручья и ветра
в жабе эту хуйню больше пяти лет назад заоптимизировали, заметьте, что питон старше жабы.
Обёртки делающие что-то новое — обёртки над обёртками.
да жаба вообще молодцы, и денег больше зарабатывают
в питоне тоже заоптимизировали. Просто ОП использует маргинальные интерпретаторы
недозаоптимизировали. Все равно тормоз же (в 200 раз!)
чувствую — где-то подьёбка, а где — понять не могу...
:-)
его задепрекейтили в python 3
а почему?
http://stackoverflow.com/questions/46513...
о, так тем более. bytearray намного лучше, не надо лишних импортов делать
ага, всего-то encode-decode все время хуячить в bytearray. Нет спасибо.
There are no mutable unicode strings, because this is considered an uncommon application, but you can always implement __unicode__ (or __str__ for Python 3) and encode methods on your custom sequence type to emulate one.
предлагает написать свой UnicodeBucket, прикинь
уфф. Пусть будет так
нет, ну я все равно пойду использовать [] + join, потому что накладно и лень его импортировать везде, но тем, кто UnicodeBucket будет использовать по яйцам стучать не стану
такой себе "исторический хак"
нет, передумал, назову его StringBuilder и буду использовать, всё же так правильней, и его можно документировать (четко написать зачем он нужен, в отличии от [] + join). А еще в нём кеширование есть, так что просчитываться будет один раз только.
не забудь очистку кеша на +=
вроде не забыл, ага