Сучасна диджитал-освіта для дітей — безоплатне заняття в GoITeens ×
Mazda CX 30
×

Мой любимый неторопливый питон

Я люблю язык программирования Питон. Люблю как программист и как пользователь. Я люблю использовать программы, написанные на этом языке. В списке моих излюбленных инструментов находятся 3 великолепные питон-программы:

  • для ведения документации я использую пакет docutils (docutils.sf.net)
  • для сборки сишных проектов я использую SCons (www.scons.org)
  • для ведения истории моих проектов я использую децентрализованную систему контроля версий Bazaar (www.bazaar-vcs.org)
Эти 3 программы объединяет 2 свойства:

1) они написаны на питоне
2) они медленно работают (как ни горько это сознавать)

Причем 2е неявно вытекает из 1го. Причем медленность эта проявляется в 2х случаях:

1) на медленных старых машинах
2) на больших объемах данных для обработки

И если с 1м фактором бороться как-то можно (но не всегда), то 2й фактор порой действует просто убийственно.

Все мы (или по крайней мере многие из нас) знаем, что Питон медленный, и не рекомендуется для обработки огромных массивов данных. Что на нём очень быстро и удобно писать программы. И потому очень хорошо использовать для макетирования и прототипирования.

Но где-то здесь, мне кажется, таится фундаментальная ошибка. Подвох. Обман.

При переходе от макета к рабочей версии получается нужно писать все заново на сях или плюсах? При этом или заново изобретать велосипед и вводить свои реализации высокоуровневых питон-объектов, таких как списки, словари или связанные методы, либо стараться не использовать подобные вкусности питона в макете, чтобы меньше потом переделывать? К тому же огромная мощь Питона отчасти обеспечивается его огромной стандартной библиотекой, включая огромный арсенал дополнительных средств. Как быть с ними? Да и его кросс-платформенность многого стоит. На самом деле.

Возможно введение необязательной статической типизации в Питоне 3000 как-то поможет в проблеме создания высокоэффективных jit-компиляторов для Питона, либо трансляторов в C++. Но сегодня... М-да.
Остается только надеяться, что однажды можно будет в C(D?) программе написать:

for item in some_list:
do_something(item)
А пока можно поизвращаться с игрушками типа p++ и ShedLight.

Все про українське ІТ в телеграмі — підписуйтеся на канал DOU

👍ПодобаєтьсяСподобалось0
До обраногоВ обраному0
LinkedIn



25 коментарів

Підписатись на коментаріВідписатись від коментарів Коментарі можуть залишати тільки користувачі з підтвердженими акаунтами.

) начали с петон, а закочели плюсами:) Психи нах, а не девелоперы, смешно!)

1) по стандарту, return в конце main () не обязателен, так что все скомпилится; 2) проблема в gcc 3.2 и 3.3 — в остальных версиях (я проверял еще 4.1, 3.4 и 2.95) все работает, как и должно.

Приведенный код gcc точно не скомпилит — в конце main return пропущен.#include < iostream> extern int getpid (); template< class T> static void foo (const T& func) {std: cout << func () << std: endl;} int main () { foo (getpid); return 1; } test.cpp: In function

int main()':<br>test.cpp:7: no matching function for call to

foo (int (&) ()) ’ Тестил под mingw$gcc —versiongcc (GCC) 3.2.3 (mingw special 20030504−1) Copyright© 2002 Free Software Foundation, Inc.This is free software; see the source for copying conditions. There is NOwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

koder:

gcc 4.1 не компилит. Основная причина — для функции нет способа указать что она не меняет static переменные (или что у нее таких нет) и соотв. непонятно изменится ли ее внутренние состояние.

у меня (gcc 4.1.2) все компилится:

template<class T>static void foo( const T& func ) { std::cout << func() << std::endl; } int main(){     foo(getpid);}

в случае с foo (getpid) T имеет тип указателя на функцию, т.е. в foo () передается ссылка на константный указатель. поскльку внутри foo () мы этот указатель не меняем, все должно быть ок. статические переменные тут ни при чем.

Насчет использования Bazaar — то Mercurial побыстрее будет. В разы. http://weblogs.mozillazine.org...

gcc 4.1 не компилит. Основная причина — для функции нет способа указать что она не меняет static переменные (или что у нее таких нет) и соотв. непонятно изменится ли ее внутренние состояние.

koder:

если бы у себя в прототипе я написал

template<class X,class Y> int for_each(X &,const Y &){...}

то вместо Y уже нельзя было-бы подставить ф-цию.

хмм... что-то я не врубился. почему указатель на функцию нельзя передать по конст ссылке? должно работать.

Ничего личного)), просто после рекламы mkdir’a зашел на очередной порталпрограммистов и нашел всех старых знакомых, коих обсуждаю уже лет 5.И про скорость питон программ и про то что кому не нравится, до полного набора нехватает только «Почему я никогда не променяю Java/C++/C#/Lisp/... на питон».Но в этой статье хоть оригинальность проявлена. Вот с этой фразой я полностью согласен

Но где-то здесь, мне кажется, таится фундаментальная ошибка. Подвох. Обман.

. Тепьрь я понимаю что периодически у меня подобные ощущения были, только буквами не оформлялись. Это когда после профилировки иногда приходится самые pythonic куски переписывать ((.

Товарыш koder вышел на тропу войны??? Ховайся хлопцы. (Всем жарко, не только вам, так что иногда стоит сливать кипяток.) В целом я написал несерьезную и в чем-то провокационную статью. Признаюсь.Перечитайте ее название. Про сконс можно говорить долго и нудно. Начал его пользовать два года назад и периодически читал список рассылки (как user, так и dev). Вы привели ссылки на обсуждения 2004 года. Я читал в 2005−2006 годах. Проблемы все еще оставались. И в 2007 году они никуда не делись. У сконса вообще очень жесткая политика разработки, может последний год что-то поменялось, не знаю.Пока что для меня панацеей от медлительности питона было и остается использование быстрой машины.В дискуссии про С++ влазить не буду, потому что я не люблю этот язык.

хм. ну тогда можно было и поближе найти, как мне кажется. питоновский map (), насколько я понимаю, возвращает новый список

Да, с map я описался, он тут совсем не причем, приведен пример соотв. требуемомуfor i in storage: func (i)

ну это и ежу понятно. впрочем, если придираться к словам,

Придиратся к словам начали Вы, это был просто ответ в том-же духе.

my guess — это просто потому, что в питоне все передается по ссылке

+1. Так-же потому что иногда объект накапливает определенную информацию при прохождении массива, что используется уже после цикла/map.

surprise, surprise — передача по значению и стандартные алгоритмы прекрасно работают с обычными С функциями, напр

Я и не говорил что они не могут, но вот если бы у себя в прототипе я написалtemplate< class X, class Y> int for_each (X &, const Y &) {...} то вместо Y уже нельзя было-бы подставить ф-цию. Это был ответ на

и что функциональный объект передается по значению. (вопрос «зачем» оставляем читателям в качестве упражнения)

, насколько я понял именнона невозможность использования ф-ций с const X & и намекалось.

впрочем, я другое хотел сказать с самого начала: в каждом языке есть свои паттерны и идиомы, и нечего в С++ лепить свой for_each (), если уже есть STL. он не такой, как map () в питоне, но и С++ другой язык.

Тоже +1. Просто люблю плюсы и шаблоны, а тут вот пишут такое:

Остается только надеяться, что однажды можно будет в C (D?) программе написать: for item in some_list: do_something (item)

koder:

Приведен ПРИМЕР наиболее близкий к питоновскому map (function, object).

хм. ну тогда можно было и поближе найти, как мне кажется. питоновский map (), насколько я понимаю, возвращает новый список — это ближе к std: copy () или std: transform () + insert_iterator, но никак не к for_each (), тем более в том виде, в каком вы его написали.

В stl отдельным параметром передается не только конец контейнера, но и егоначало (собственно контейнер вообще не передается).

ну это и ежу понятно. впрочем, если придираться к словам, то стандартные алгоритмы вообще не знают ни про контейнеры, ни про их «начало» и «конец». пример — тот же std: for_each () + std: istream_iterator.

Теперь предлагаю motus поупражнять знание питона и подумать почему я передалфункциональный объект по ссылке (намекаю — это было сделано специально).

я питон знаю плохо, но упражняться люблю. my guess — это просто потому, что в питоне все передается по ссылке. теперь, пожалуйста, скажите правильный ответ.впрочем, я другое хотел сказать с самого начала: в каждом языке есть свои паттерны и идиомы, и нечего в С++ лепить свой for_each (), если уже есть STL. он не такой, как map () в питоне, но и С++ другой язык.

И, кстати, этот пример замечательно работает не только к функторами, но и сфункциями.

surprise, surprise — передача по значению и стандартные алгоритмы прекрасно работают с обычными С функциями, напр.

std::transform(str.begin(), str.end(), str.begin(), toupper);

В догонку. Просмотр списка рассылки scons указал на то что основная частьпроблем (кстати всего ~10 небольших тредов затрагивают производительность за более чем 3 года при более 10000 писем в рассылке в сумме) связанна как раз с неоптимальными алгоритмами, а не с торможением собственно питона.Пример: http://scons.tigris.org/servle....этот то-же поучительный http://scons.tigris.org/servle... (только не останавливаемся на первом письме, а читаем дальше) Так-же можно обратится к проектам Scons на Google SOC (http://www.scons.org/wiki/GSoC...) — там тоже ничего про общуюоптимизацию, а только улучшение алгоритма отслеживания измененных файлов.

bialix:

А вот Вы лично и сходите в список рассылки тех же docutils и scons и поучите их уму-разуму. А то ребята который год не могут правильный алгоритм выбрать.

docutils не использовал, а производительность scons вполне приемлемая. В любом случае компилятор съедает основную часть времени (в случае с docutils могу сказать что крайне низкая скорость работы LaTeX почему-то никого не волнует). Ваша статья затрагивает их только как пример, а дальше идет рассуждение на тему какой питон тормоз и что нет от этого спасения так что и советы не относились к ним конкретно, а имели общий характер.

Если честно — все написанное Вами настолько тривиально и избито...

Безусловно, но написанное в заметке ему явно противоречит.А именно это:

При переходе от макета к рабочей версии получается нужно писать все заново на сях или плюсах?

, на что и был ответ, что нет, не все нужно переписывать (кроме некоторых исключений), в основном можно обойтись малой кровью (примеров масса — cheetah один из них).

И пока что решается только одним путем — использования самого быстрого компьютера из имеющихся.

Программы типа scons безусловно не расчитаны на Celeron 300, там Вас толькоmake и спасет. Я предлагаю Вам привести пример быстрых систем, подобных по возможностям к scons (желательно не тормозящих на указанной машине).Для примера — jam (boost) тормозит если и меньше, то несущественно.И AFAIK обладает существенно меньшим количеством возможностей.motus:

: -) учите устав STL, двоечники — std: for_each () уже сто лет как стандарт. заодно рекомендую обратить внимание, что в STL конец контейнера передается отдельным параметром, и что функциональный объект передается по значению. (вопрос «зачем» оставляем читателям в качестве упражнения): -)

Приведен ПРИМЕР наиболее близкий к питоновскому map (function, object). В stl отдельным параметром передается не только конец контейнера, но и его начало (собственно контейнер вообще не передается).Теперь предлагаю motus поупражнять знание питона и подумать почему я передалфункциональный объект по ссылке (намекаю — это было сделано специально).И, кстати, этот пример замечательно работает не только к функторами, но и сфункциями.

Однако программы написанные на Java/.NET тоже медленны (по сравнению с C++).

Если это не вычислительные задачи (типа перемножения матриц), то в среднем С# отстаёт от С процентов на 20. Языки же вроде питона и руби проигрывают в разы!

Низкая скорость питона имеет место быть. Однако программы написанные на Java/.NET тоже медленны (по сравнению с C++). Это — расплата за вкусности и кросплатфоренность. И действительно, бороться с этим можно только переводя части кода на более быстрые языки. И конечно использовать только к подходящим задачам.Бо "Нема на то ради"©

Медленно работают? А есть причины полагать что можно быстрее? Может просто действительно данных очень много?

Есть причины полагать, что да. Эта причины — программы-конкуренты.Но данных действительно очень много. Порой.В общем еще одна вещь, от которой спасает только быстрая машина — это очень медленный старт самого интерпретатора Питона. Вы пробовали когда-нибудь запустить Питон на Целероне 300 МГц? Вот когда узнаешь, что значит слово «терпение» : -)

Медленно работают? А есть причины полагать что можно быстрее? Может просто действительно данных очень много?

в последней версии boost вроде появилась конструкция FOR_EACH

Она на С++ пишется на раз и без всякого boost: -) учите устав STL, двоечники — std: for_each () уже сто лет как стандарт. заодно рекомендую обратить внимание, что в STL конец контейнера передается отдельным параметром, и что функциональный объект передается по значению. (вопрос “зачем” оставляем читателям в качестве упражнения): -)

меня удивляет, почему Гугл с их гуглоподобными объемами данных пишут на этом языке

насколько я знаю, в гугле питона не так много, как все считают... пару лет назад была презентация на эту тему: python at google... гугл, кстати, активно использует SWIG — странно, что про него никто не вспомнил.еще вроде популярный вариант — Boost: Python, но я его не использовал никогда.

колись Yahoo! відкрила свій власний документ про переваги переходу з YahooScript на PHP.

yScript. это не внутренний документ, и не один. ты скорее всего про это: http://www.radwin.org/michael/...хотя, наверное, более ранняя презентация информативнее: http://public.yahoo.com/bfranc...а вот тут они все: http://public.yahoo.com/bfranc...

почему Гугл с их гуглоподобными объемами данных пишут на этом языке (вернее, в том числе на этом)

Як варіант відповіді — Python використовується на “вищому” рівні для поєднання компонент, написаних на C/C++.Хоча, дійсно, існують і інші мови програмування високого рівня з швидкими інтерпретаторами/компіляторами.PS.: колись Yahoo! відкрила свій власний документ про переваги переходу з YahooScript на PHP.

предлагаю пререписать на ассемблере

Я далекий от питона человек, но, учитывая написанное выше, меня удивляет, почему Гугл с их гуглоподобными объемами данных пишут на этом языке (вернее, в том числе на этом).

Теперь по делу собственно: 1) В основном низкая скорость обусловлена кривым алгоритмом, а не языком

А вот Вы лично и сходите в список рассылки тех же docutils и scons и поучите их уму-разуму. А то ребята который год не могут правильный алгоритм выбрать.Если честно — все написанное Вами настолько тривиально и избито... Однако проблема все равно имеет место быть. И будет. И пока что решается только одним путем — использования самого быстрого компьютера из имеющихся.

в последней версии boost вроде появилась конструкция FOR_EACH

Она на С++ пишется на раз и без всякого boost

template for_each(Cont & cont,Callb & callb){Cont::iterator it = cont.begin();for(;it != cont.end();++it)callb(*it);}

Теперь по делу собственно: 1) В основном низкая скорость обусловлена кривым алгоритмом, а не языком, я одинраз в весьма серьезной научной программе пузырьковую сортировку нашел, а ееавтор долго удивлялся че это она так тормозит на больших объемах данных.2) В нете есть вагон документации по оптимизации питоновских программ. Чаще всегоне нужно переписывать всю прогу, а достаточно прооптимизироватьсамые «жрущие» проц. ф-ции/блоки. Причем сначало psyco затем PyRex и только затем pure-C/C++. После применения этого метода лично меня результаты по скоростивполне устраивали.3) Используйте правильные библиотеки (типа scipy) — это решает массу проблем (если они есть, конечно, но чаще всего они таки есть).

По поводуfor item in some_list: в последней версии boost вроде появилась конструкция FOR_EACH.

Підписатись на коментарі