perl: лучше всего подходит для простых "однострочных" програмок, обрабатывающих (текстовый)поток|файл. Если программа чуть побольше - лучше не использовать.
python: хорош почти везде, но однострочник на нем практически невозможен.
ruby: если тебе не нравится синтаксис питона или очень нравиться perl и програмка не тривиальна.
Скорость у всех не очень, но есть оптимизированые библиотеки и "обходные" пути. Например, psyco (говорят) может ускорить python-код на порядки.
Добавлю. Если нужна обработка текста регэкспами - то перл однозначно (он вырос из регэкспов, они в нем органическая часть языка, а в рабби и, особенно, пистоне регэкспы пришлепнуты сбоку). Если обработка текста не нужна - то языки практически равнозначны, пистон чуть поприятнее.
> perl: лучше всего подходит для простых "однострочных" програмок, обрабатывающих (текстовый)поток|файл. Если программа чуть побольше - лучше не использовать.
чуть побольше?
это сколько? 10 000 - 15 000 строк кода это чуть побольше или не чуть?
работает на ура!!!
касаемо ruby могу сказать, что в скорости он уступает perl на порядок. По крайней мере так было года 2 назад, когда тесты проводил.
+ в перл, imho, более приятно организовано расширение возможностей языка через подключение модулей.
Автору: сходи на www.cpan.org
посмотри сколько там инструментов предлагается для решения самых разнообразных задач.
PS: Против перла я никогда не был, но пока пользуюсь питоном, потому как синтаксис мне его нравится. А из вприведенной фразы следует, что подключение модулей в питоне если есть, то полная "жопа", ИМХО, это не так.
> Добавлю. Если нужна обработка текста регэкспами - то перл однозначно (он вырос из регэкспов, они в нем органическая часть языка, а в рабби и, особенно, пистоне регэкспы пришлепнуты сбоку).
Поясню: то, что автор комментария называет "пришлепнуты сбоку" означает -- реализованы в виде библиотек (Про Ruby не скажу, я его совсем не знаю, а в Python именно так).
В результате, в простых случаях в Perl код получается проще и короче. В Python всё несколько сложнее, там результат поиска не строка, а более сложный объект, который кроме найденной строки содержит дополнительную информацию. В итоге в Python код обычно получается длиннее, но зато появляются дополнительные возможности. Например, в Perl нелегко найти позицию найденной строки в исходной, а в Python эта информация содержится в объекте-результате поиска.
Ещё один плюс библиотеки: её легче развивать и дополнять, чем изменять синтаксис (в Perl регулярные выражения -- часть синтаксиса).
Ну и плюс дополнительные мелочи: в обоих языках есть функция split, позволяющая сделать из строки список(массив), задав шаблон разделителя. В Python, кроме того, есть функция findall, выполняющая похожее действие, но которой нужно задать шаблон элемента списка.
> Если обработка текста не нужна - то языки практически равнозначны, пистон чуть поприятнее.
В задачах обработки текста Python тоже ничем не уступает.
> > называет "пришлепнуты сбоку" означает -- реализованы в виде библиотек
> С откровенно неудачным и неудобным (зато "привычным и единообразным") интерфейсом.
В чём неудачность и неудобство? Желательно с примерами.
Возможность откомпилировать регексп и потом использовать откомпилированный, это неудачно или неудобно?
> > в простых случаях в Perl код получается проще и короче.
>В сложных тоже.
Короче в любом случае -- наверное, да. Но проще, означает ещё и легче для написания и прочтения. А для этого часто легче сделать сложное действие в несколько этапов: сначало получить результат поиска, потом проделать с ним какие-то действия.
> В самых сложных для _любого_ языка придется использовать lex&yacc.
Существует реализация (правда, не совсем полная) на чистом Питоне. Занятная вещица. :)
> > Например, в Perl нелегко найти позицию найденной строки в исходной,
>Вот уж чего совсем не надо делать.
"Нет, значит не надо" или "не надо мне, значит не надо другим"? Извините, не аргумент. По крайней мере, один раз в питоновской рассылке такой вопрос пробегал. Возможно, он возникал и у других, но они нашли ответ сами.
> > Ещё один плюс библиотеки: её легче развивать и дополнять,
> > В задачах обработки текста Python тоже ничем не уступает.
> Уступает. :(
См. предыдущие пункты. Кроме того, большинство реальных задач, если это не простой фильтр, преобразующий один текстовый формат в другой, не сводится только к обработке текста, а содержит достаточно сложную логику. В этом случае большое значение приобретают другие возможности языка, не связанные с обработкой текста.
> В чём неудачность и неудобство? Желательно с примерами.
Ну как мне кажется:
Код намного длиннее и мутнее. Не очень удобно писать многострочные регэспы.
Очень буду рад, если вы найдете _мой_ промах, но напишите на питоне аналог s/%%(.*?)%%/$1/gee;
> Возможность откомпилировать регексп и потом использовать откомпилированный, это неудачно или неудобно?
Неудачно, потому что появляется дополнительная переменная и что же она делает неочевидно: приходится постоянно возвращаться к ее определению.
Вы ведь ратуете за удобство для прочтения и, наверное, используете легкочитаемые имена переменных, не могли бы вы привести несколько пар: регэксп и имя переменной для него.
> Существует реализация (правда, не совсем полная) на чистом Питоне.
Не знаю как _на_ perl, а _для_ perl подобные вещи тоже есть.
> "Нет, значит не надо" или "не надо мне, значит не надо другим"? Извините, не аргумент.
Ну а для чего это может быть нужно? Выделить подстроку - так это значение уже есть. Изменить переменную - гнилая затея, в языках высокого уровня все переменные должны быть write-once.
> В этом случае большое значение приобретают другие возможности языка, не связанные с обработкой текста.
Не соглашусь. Эти остальные возможности имеют значение только если возможности по обработке текста одинаковы.
>>С неудачным и неудобным (зато "привычным и единообразным") интерфейсом.
>В чём неудачность и неудобство? Желательно с примерами.
Всегда, кроме простейших случаев будет так:
на perl:
if(/blablabla/) {
do something with $1 $2 $3;
} else {
do something else;
}
на python:
try:
a,b,c,d=re.match(line)
do something with a b c d
except:
do something else
или
mo=re.match(line)
if mo:
do something with mo
else:
do something else
выглядит действительно менее удобно - особенно второй вариант.
Но это скорее вопрос привычки. А длинна - практически такая же.
> > в простых случаях в Perl код получается проще и короче.
>В сложных тоже.
В сложных - нет. Перл _длиннее_ и _сложнее_ в многочисленных -> {} $ @
на достаточно сложных обьектах. При этом "теряется" начальное преимущество - многочисленные импорты питона уравновешиваются use-ами.
Остается только выигрыш на "укороченых" операторах - m//, s//, и
"коротких" управляющих операторах типа "do this until condition".
То есть perl короче - на уровне процентов. Зато читаемость хуже.
Что кому более важно?
> Очень буду рад, если вы найдете _мой_ промах, но напишите на питоне аналог s/%%(.*?)%%/$1/gee;
Я уже подзабыл опции поиска в Перле и совсем не понял, что означают две буквы 'e', поэтому могу ошибиться. Если я правильно понял, то на Питоне будет так:
new_line = re.sub('%%(.*?)%%', r'\1', line)
где line содержит исходную строку. При этом line не изменяется -- отсутствует побочный эффект. Цитирую: "Изменить переменную - гнилая затея, в языках высокого уровня все переменные должны быть write-once." :)
> Вы ведь ратуете за удобство для прочтения и, наверное, используете легкочитаемые имена переменных, не могли бы вы привести несколько пар: регэксп и имя переменной для него.
Для составления регекспов для более сложных случаев, нужно затратить приличное время, чтобы учесть все тонкости. Даже выражение для выделения действительного числа может оказаться весьма непростым. Я думаю, что всё же проще догадаться, для чего служат переменные url_pattern, file_name_pattern, mail_address_pattern, чем разбираться в достаточно сложных регекспах, из которых они были получены. Ведь вы же определяете и вызываете функции, а не копируете каждый раз куски кода? А если в очередной версии программы шаблон нужно будет изменить? К тому же, насколько я понимаю, использование предварительно откомпилированных выражений улучшает производительность.
Встречный вопрос на засыпку: как в одной программе в одних случаях применять локаль при поиске/замене, а в других нет?
> Ну а для чего это может быть нужно? Выделить подстроку - так это значение уже есть.
Ну, мало ли для чего. Например, присвоить найденной подстроке некий вес, в зависимости от положения подстроки в тексте или расстояния до соседней подстроки. Или, попроще: составляем индекс. Пусть у нас есть информация, в каких позициях начинаются страницы. Тогда, зная положение подстроки, знаем на какой она странице. Примеры, конечно, от балды, сам только что придумал, но если не нужно большинству, это не значит, что не нужно никому.
Кстати, в Перле это тоже возможно, но IMHO менее удобно.
Вот примерный код. Не проверен. Вызов: sgee('%%(.*?)%%',templateText).
Не понятно что должно быть между %% - пример бы.
def sgee(pattern,line):
pat=re.compile(pattern)
exprs=[str(eval(eval(x))) for x in pat.findall(line)]+['']
strings=pat.split(line)
return ''.join([ a+b for (a,b) in zip(strings,exprs)])
Блин.
> Я уже подзабыл опции поиска в Перле и совсем не понял, что означают
две буквы 'e
eval. То есть фактически eval(eval($1)).
> Ведь вы же определяете и вызываете функции, а не копируете каждый
раз куски кода?
Зачем? Почему не поручить это компилятору? :) Пример:
http://iis1.cps.unizar.es/Oreilly/perl/cookbook/ch10_16.htm (Это
шутка).
Про такие имена переменных теперь согласен.
> Встречный вопрос на засыпку: как в одной программе в одних случаях
применять локаль при поиске/замене, а в других нет?
В каких случаях _не_ нужно применять локаль?
#!/usr/bin/perl -w
use locale;
while(<>)
{
s/(\w+)/\U$1/g;
print "$_\n";
{
no locale;
s/(\w+)/\L$1/g;
print "$_\n";
}
}
$ ./test2.pl
Привет World!
ПРИВЕТ WORLD!
ПРИВЕТ world!
До свидания world!
ДО СВИДАНИЯ WORLD!
ДО СВИДАНИЯ world!
> Кстати, в Перле это тоже возможно
Это про @- @+ ?
> Не понятно что должно быть между %% - пример бы.
%%join " ", (localtime)[7,8]%%, %%$data{'abcd'}{'efgh'}[0]%%, %%$a ? $b :$c%% Да мало ли что.
Кстати очень интересен для питона и аналог "Текст @{[ какой-то код ]} и еще текст".
Пример, по-моему делает подстановку немного неправильно (или я не понимаю логику питоновской split - там (*.?) не попадет в результируюший список?) и кроме того проходится по строке дважды. Да и писать функцию на каждый чих...
>"Текст @{[ какой-то код ]} и еще текст"
Это же очевидно: "Текст %s и еще текст"%(какой-то код)
Посмотрел, что делает перловый код. Пример действительно делает не то.
Вот более близко(работает только при ровно 1й группе () в pat):
def sgee(pat,line):
strings=re.split(pat,line)
return ''.join([(lambda x:x,eval)[i%2](s) for (i,s) in enumerate(strings)])
Нашел и более простой метод:-)
''.join(['Текст ',код,'еще текст',еще код,...]
В этом случае вместо "%%" используются "'," и ",'" - что дело вкуса;-)
Извиняюсь за долгое молчание. Посмотрел что означает опция 'ee'. Круто завёрнуто :). Я сам ни с одним ни с двумя 'e' не сталкивался, т.к. не использовал шаблоны, содержащие перловый код. Знаю, что на Перл эта технология весьма популярна, но сам я применял другой подход: накатал на Перле простенький интерпретатор TCL-подобного языка и использовал его в шаблонах. По поводу конструкции с 'gee': по видимому, ближайшим аналогом на Питоне будет
для двух. Разумеется, код в шаблоне должен быть питоновский. Получается, конечно, длиннее, но вполне реализуемо. И, что делает этот код, IMHO достаточно очевидно.
> PS Можно было бы еще поприводить примеров с (?{...}) и еще пару штук с /e, это убедит, что в perl с регэкспами работать удобнее? :)
По пунктам:
По поводу (?{...}) не понял (возможно, что-то упустил). В Питоне это есть.
По поводу /e. Да, в Питоне нет специальной конструкции для поддержки шаблонов, содержащих код. Ну и что? Во-первых это реализуется средствами языка (хотя и более длинно), во-вторых это касается только одного класса задач. Нельзя обобщать на все задачи обработки текста.
По поводу "в perl с регэкспами работать удобнее". Возможности собственно регекспов в Перл IMHO мало отличаются от таковых в sed и awk. Но Ларри Уолла почему-то эти инструменты не устроили, и он создал полноценный язык программирования. Значит, решение практических задач обработки текста не сводится к применению регекспов, нужно что-то ещё. И отличия Питона от Перла лежат как раз в области этого "чего-то ещё".
> По поводу (?{...}) не понял (возможно, что-то упустил).
Возможно я что-то упустил. (последнее серьезное сравнение perl/python делал пару лет назад). Для perl знаменитым применением этой фигни была проверка сбалансированности скобок регэкспом. Можно ссылку на аналогичный python'овский пример?
> Возможности собственно регекспов в Перл IMHO мало отличаются от таковых в sed и awk.
Вообще-то это не так. Совсем не так. Задумайтесь, почему стало популярно хвастаться "perl-совместимыми" регэкспами.
> И отличия Питона от Перла лежат как раз в области этого "чего-то ещё".
Разговор шел про обработку текста.
Что-то еще - что еще? Да, в perl нет дешевых списков (и вообще ничего дешевого), но если они мне будут нужны - я возьму scheme, а не python.
> А в файле то же, что и у Вас:-)
текст',код,'снова текст',снова код,'
Текста много и он разный (в т.ч. и с кавычками, \ и т.д.). Вставок мало и их желательно выделять более заметно, чем запятыми. А то было бы совсем просто - do "имя файла" :)
А что еще можно захотеть засунуть в регексп? ;-) Для решения задач нужно пользовать подходящие инструменты, а не те, с которыми работать удобнее. Т.е. данную задачу регекспами решать не стоит. В перле она решается тоже не регекспами - а встроеным в них кодом. Так что воспользовавшись подсказаным DK свойством python re можно сказать:
try: re.sub(r'([\[\](){}',pCheck) ...
except КривыеСкобки: ошибка
где ф-я pCheck будет считать скобки и бросать исключение "КривыеСкобки" в случае несовпадения. Тривиально.
>Разговор шел про обработку текста.
Разговор шел про _простую_ обработку текста, гле перл удобнее. И про то, что на _непростой_ (и не только текста) - нет.
> > По поводу (?{...}) не понял (возможно, что-то упустил).
> Возможно я что-то упустил. (последнее серьезное сравнение perl/python делал пару лет назад). Для perl знаменитым применением этой фигни была проверка сбалансированности скобок регэкспом. Можно ссылку на аналогичный python'овский пример?
Извиняюсь, невнимательно посмотрел, перепутал с другими конструкциями, содержащими "?". Возможно, в Питоне этого действительно нет, в доке на модуль 're' я ничего похожего не нашёл. В Перле я этой возможностью не пользовался (не знал), поэтому не сразу понял о чём речь. Нужно будет посмотреть.
> > И отличия Питона от Перла лежат как раз в области этого "чего-то ещё".
> Разговор шел про обработку текста.
Я имею в виду, что обработка текста не сводится к применению регекспов, иначе был бы не нужен нормальный язык программирования (ни Перл ни Питон), достаточно было бы аналога awk с более продвинутыми регекспами. Типичные задачи обработки текста предполагают различные (иногда, довольно сложные) действия с извлечённой из текста информацией. И здесь немаловажное значение имеют другие возможности языка. В качестве примера такой задачи приведу PythonDoc -- программу для создания документации по питоновскому коду (аналог JavaDoc для Питона).
> Что-то еще - что еще? Да, в perl нет дешевых списков (и вообще ничего дешевого), но если они мне будут нужны - я возьму scheme, а не python.
Дешёвые, это что? Типа tuple в Питоне?
Что ещё есть? Более последовательная поддержка ООП (для сложных задач это важно). Динамическая проверка типов. По мелочи -- удобная работа с индексами.
По поводу scheme, согласен, ФП рулит, но не каждый сможет перескочить на ФП язык. А в Питоне поддержка ФП довольно неплохая для императивного, по сути, языка.
> Этот регэксп посчитает соответствие числа открывающих скобок одного типа числу закрывающих?
Подсчитает функция pCheck, которой доступна информация о найденной подстроке. А там подсчитывай, что хочешь, хоть begin/end, если их в регекспе указать :-).
IMO смысл в том, чтобы писать 1 раз программу - а данные - сколько захочется. Посему изобретать s/что_угодно... и так для _каждого_ шаблона - неправильно.
А вот и доказательство:-) Не писать именованаые функции можно себе позволить только в случае тривиальных кусков кода. Из тривиальных кусков нетривиальную программу получить трудно (-: точнее получить легко, отлаживать и сопровождать - увы:-) -> преимуществами перла в нетривиальных(или просто больших) задачах _приходится_ не пользоваться(-:если вы не мазохист:-)
Было сказано про "чих", то есть именно тривиальные куски кода.
Засорять программу именованными однострочными функциями - недопустимо, IMHO. Так как "тривиальные куски" будут выглядеть слишком похоже на нетривиальные. Краткость юбер аллес.
cons это, насколько я понимаю :) функция такая в лисп и подобных языках. А чем определяется дешевизна?
> > Что ещё есть? Более последовательная поддержка ООП (для сложных задач это важно).
> Точнее больше соответствующая традициям С++.
ОО-модель Питона писалась не с Си++, а с Модулы и Смоллтока (если я не ошибаюсь). С Си++ сравнивают как с более известным.
> > Динамическая проверка типов.
> В perl вроде есть. (не использую)
Строки, действительные и целые числа относятся к разным типам? В Питоне -- да. Правда, в коротких скриптах это только мешает, но для больших программ IMHO полезно.
> cons это, насколько я понимаю :) функция такая в лисп и подобных языках. А чем определяется дешевизна?
Имелись в виду пары (ну туплы такие двухэлементные :)). В perl пришлось бы строить список на массивах из двух элементов каждый. Что-то сомневаюсь в дешевизне такой реализации.
> ОО-модель Питона писалась не с Си++, а с Модулы и Смоллтока (если я не ошибаюсь). С Си++ сравнивают как с более известным.
Один черт.
> Строки, действительные и целые числа относятся к разным типам?
А почему они должны относиться к разным типам? Потому что так принято в остальных языках? Базовые типы perl - скаляр, массив, хэш и т.д.
> В Питоне -- да. Правда, в коротких скриптах это только мешает, но для больших программ IMHO полезно.
> > ОО-модель Питона писалась не с Си++, а с Модулы и Смоллтока (если я не ошибаюсь). С Си++ сравнивают как с более известным.
> Один черт.
Просто, объектную модель Перла я с ходу не смог понять. С Питоном всё было гораздо проще. Конечно, это субъективное мнение, но IMHO в Перле ООП действительно немного "сбоку".
> > Строки, действительные и целые числа относятся к разным типам?
> А почему они должны относиться к разным типам? Потому что так принято в остальных языках? Базовые типы perl - скаляр, массив, хэш и т.д.
В некоторых языках (TCL) вообще один тип -- строка. В Лиспе типы различаются. А контроль типов нужен, чтобы не складывать яблоки с апельсинами.
> > Шаг,
> Что это?
В срезах, кроме начала и конца, можно задать шаг (по умолчанию 1). Если задать отрицательный шаг и переставить начало и конец, получим обратный порядок.
> > отрицательные индексы?
> Разумеется.
А что они означают в Перле? В Питоне это отсчёт от конца последовательности (a[-1] -- последний элемент).
У меня сложилось впечатление, что оно на самом деле _почти_ такое же внутри - а синтаксис действительно сбоку.
>скаляр с массивом спутать сложно.
А я до сих пор иногда ставлю неправильную операцию сравнения строк в перле. Все время приходится быть начеку. Не дает расслабиться гад:-)
>когда это может повредить, и какие в _python_ есть способы это обойти.
Простейший пример: что может означать выражение "яблок+апельсинов" - при разных типах переменных? К примеру яблок=вес/float, апелисинов=количество(int), или цвет(перечислимый тип) или сорт(строка). Перл скушает, не поперхнувшись, и выдаст неправильный результат. Питон с большой вероятностью забросает исключениями. Даже если типы одинаковы - не всегда можно их складывать(последние 2 случая).
>А ленивые списки в питоне есть?
Похоже есть некоторое приближение - это называется то ли итераторами, то ли генераторами. Не Хаскель, но все же.:-)
"Сбоку" было частично в отместку за высказывание о регулярных выражениях в Питон :-). Но если посмотреть, ведь Перл на самом деле не поддерживает напрямую ООП, оно в нём эмулируется с помощью механизма пакетов. В результате, очень много приходится делать руками. Точно так же (IMHO) создаются объектные расширения для других необъектных языков: TCL, LISP. Только там этих расширений достаточно много, а в Перле эта вещь стандартизована.
Собственно, я немного отклонился. Я не собирался и не собираюсь ругать Перл, а в эту дискуссию вступил, чтобы опровергнуть утверждение о неудобстве применения Питона для обработки текста. Увлёкся :-).
> > В некоторых языках (TCL) вообще один тип -- строка.
> Что не мешает любить и использовать такие языки. К примеру для tcl один фанатик сделал реализацию algebraic types.
А какие-то приколисты написали на TeX интерпретатор Бейсика :-))). Что доказывает, что возможности многих языков выходят далеко за рамки привычных представлений о них. Вопрос лишь в цене выхода за эти рамки.
> > В Лиспе типы различаются.
> Ну в perl тоже скаляр с массивом спутать сложно.
Я не про списки. В LISP вы не сможете проделать арифметическую операцию над строкой.
(+ 1 "2") -- облом :-).
> > А контроль типов нужен, чтобы не складывать яблоки с апельсинами.
> Хотелось бы пример, когда это может повредить, и какие в _python_ есть способы это обойти.
Пример: если нужно действовать по разному, в зависимости от типа полученного значения. На самом деле, это отличие -- свойство идеологии Питон: он каждый раз определяет, возможна ли данная операция над данным(и) типом(типами). А обход стандартный: явное преобразование типов, где программист сам указывает, что он хочет получить.
> А ленивые списки в питоне есть? В perl - да, Tie::LazyList.
Для этой цели в Питоне есть итераторы и генераторы:
def natural():
number = 1
while True:
yield number
number+=1
for i in natural():
if i>10: break
print i
Здесь "natural()" возвращает итератор, который вычисляет следующее значение при каждом обращении. Если бы он попытался сразу создать последовательность, программа бы рухнула.
Оба, отступы поехали! Забыл, что в этом режиме они игнорируются.
Повторяю код:
def natural():
number = 1
while True:
yield number
number+=1
for i in natural():
if i>10: break
print i