LINUX.ORG.RU

Сравнение Python и Ruby


0

0

Вопросы товарищам, имеющим опыт программирования как на Python, так и на Ruby.
1. Что вам нравится в Python, чего нет в Ruby?
2. Что вам нравится в Ruby, чего нет в Python?
3. Что вам НЕ нравится в Python?
4. Что вам НЕ нравится в Ruby?
5. По совокупности плюсов-минусов, какой язык под какую задачу вам нравится больше?

★★

1. Элегантность, читаемость кода, нормальный юникод. Сильно усложнён процесс написания плохо оформленного кода (отступы).

2. Говорят, ООП там лучше.

3. В 2.4 есть масса нестандартного: синтаксис print, два типа объектов. Плохая поддержка юникода в 2.4. В 3 почти всё хорошо (ну разве что странный for else).

4. Синтаксис. Сложность чтения чужого кода. Низкая производительность.

5. Не знаю ruby хорошо до такой степени, чтобы грамотно ответить.

Davidov ★★★★
()

1. "only one way to do it"(tm)
2. образцово-показательная читабельность и писабельность, отсутствие ограничений "свыше"
3. ну отступы же! )
4. руби - это темная сторона силы, посмотрите в код Rspec например. ситуация улучшается, да.
5. без разницы. каждой задаче - свой язык! DSLDSLDSL! ЛИСПЛИСПЛИСП!11 ну вы поняли.

volh ★★
()

1. Свободные функции как first class citizens (без костылей в виде foo.call). Модули с вменяемым механизмом экспорта.

2. Миксины вместо множественного наследования. Кое-что из синтаксического сахара (блоки кода, case/when, перловские q{}).

3. Отступы! (точнее отсутствие символа конца блока). Неконсистентные архаизмы вроде len().

4. Сильная ОО-направленность. Некоторые сомнительные перлизмы (punctuation variables, хвостовые if/unless). Скудная документация.

Hjorn
()

А расскажите, чем вам отступы мешают?

Даже в некошерном gedit/kate расстановка отступов необременительна, а в emacs/vim даже думать об этом не надо.

Неужели, когда вы пишете на Ruby, то отступы не ставите?

У меня за последние два года не было ни одной ошибки в программе, обусловленной неправильной расстановкой отступов. Даже несмотря на то, что иногда меняю редакторы.

Davidov ★★★★
()

в питоне ооп действительно хорош - удобен , масштабируем в плане вложенности , иерархии обьетов
недостаток питона - привязка нэмспэйсов к файловым директориям
хотя как сказать , может это и плюс :-)

kto_tama ★★★★★
()
Ответ на: комментарий от kto_tama

отступы в питоне - на самом деле это не главное , это мелочь , это дисциплинирует стиль , и про это забываешь уже на второй день
питон лаконичен и изящен

kto_tama ★★★★★
()
Ответ на: комментарий от kto_tama

> в питоне ооп действительно хорош

Он там мне нравится, но разве он не прост до безобразия? :). Или я чего-то не знаю?

Пытался прогать на ruby(RoR). Сначала радовался обилию фишек которых нет в питоне, потом наткнулся на отсутсвие доков по многим вопросам и начали вылезать глюки. Плюс ещё куча CVE на него появилось и я забил. А там py3k подоспел :). Хотя, RoR местами сильно удобней django показался(уже не помню этих мест).

Местами ruby сильно кривой. Типа нету именованных аргументов и ещё кучи всего. Или то что где-то нельзя было передать функцию как аргумент, но можно было передать блок.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

>Типа нету именованных аргументов и ещё кучи всего

вот, кстати так и не понял этого момента. чем так именованые аргументы удобнее обычного хеша?

>Или то что где-то нельзя было передать функцию как аргумент, но можно было передать блок.


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

volh ★★
()
Ответ на: комментарий от teferiincub

>Значит Python - таки светлая.

пайтон - это когда твой дзен-мастер тебе бамбуковой палкой по пятой точке, за неправильное форматирование )

>А я таки Джедай =)


как и все мы, ага.

volh ★★
()
Ответ на: комментарий от volh

> вот, кстати так и не понял этого момента. чем так именованые аргументы удобнее обычного хеша?

дефолтные значения аргументам можно присвоить?

> ну да, нередко предполагается передача блока как опционального параметра. где же кривость?

тем что часто кроме блока ничего не передашь. Приходилось огород^W блоки городить.

А ещё приходилось chomp юзать при чтении строк чтобы убрать \n. В питоне без всяких chomp нормально :)

true_admin ★★★★★
()
Ответ на: комментарий от tailgunner

> у руби есть два плюса - он expression-oriented, и у него есть нормальный private.

Это совсем не killer-фичи. Да и private не самая необходимая вещь. Если человек лезет вызывать методы которые не описаны в API значит он знает что делает.

Чем хорошо expression-oriented язык?

А ещё у ruby нет публичных переменных, всё приходилось в property запихивать

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

>дефолтные значения аргументам можно присвоить?

угу, обычный def blablabla(param="some default value")

>тем что часто кроме блока ничего не передашь. Приходилось огород^W блоки городить.


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

>А ещё приходилось chomp юзать при чтении строк чтобы убрать \n. В питоне без всяких chomp нормально :)


да вы там зажрались! ;)

volh ★★
()

кстати, самый существенный недостаток руби ( точнее Matz Ruby Interpreter ) для меня сейчас - памятежручесть. ну просто таки ДОКОЛЕ.

volh ★★
()
Ответ на: комментарий от true_admin

>> у руби есть два плюса - он expression-oriented, и у него есть нормальный private.

> Это совсем не killer-фичи


Я и не говорил о том, что они killer. Они удобны, и всё.

> Если человек лезет вызывать методы которые не описаны в API значит он знает что делает.


Если человек прячет методы, он тоже знает, что делает.

> Чем хорошо expression-oriented язык?


Выразительностью. Напиши на Питоне такое:

if (r = foo("bar")) != NULL) {
}
else if (r = foo("baz")) != NULL) {
}
/* дальше еще много foo */

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>Напиши на Питоне такое:

На питоне так не пишут.

try:
  r = foo('bar')
except:
  try:
    r = foo('baz')
  except:
    ...

Ну или в крайнем случае:

for a in args:
  r = foo(a)
  if r: break;
else:
  ...

Конструкция if ((a=b())!=NULL) в редких случаях (malloc, fopen) бывает полезной. 

Davidov ★★★★
()
Ответ на: комментарий от Davidov

>> Напиши на Питоне такое:

> На питоне так не пишут.

Конечно. Так писАть на Питоне просто невозможно.

> try:
>  r = foo('bar')
> except:
>  try:
>    r = foo('baz')
>  except:

Этот стиль 1) гораздо более многословный; 2) при проверке многих случаев получается глубокая лестница (которая, кстати, противоречит смыслу программы).

tailgunner ★★★★★
()
Ответ на: комментарий от Davidov

вынудили зарегаться :( между прочим из меня был образцово-показательный анонимус

1. try это далеко не if по производительности, так что подойдет такое решение далеко не всегда.

2. http://pastie.textmate.org/private/bv0wxfbruai7scynldgnlw

mholub
()

Говорю только то, в чем уверен. Ибо python знаю лишь в теории, мелкие скрипты не считаются

1. Куча отлаженных либ на все случаи жизни. 
2. В целом язык более логичный.
3. В питоне не понравилось, что часть методов зачем-то сделана функциями - пример length(string), ООП как будто прикручено хрен знает как (ни тебе private, первым аргументом метода должен быть self).
4. Хреновая многопоточность, к сожалению пока не могу сказать, как хорошо обстоят дела в 1.9 ветке, которая кстати уже production-ready.
5. python для скриптов в Linux, требующих каких-то малораспространенных API, которых у ruby нет. ruby для web-dev'а и скриптинга всего остального.

mholub
()
Ответ на: комментарий от tailgunner

>Так писАть на Питоне просто невозможно.

Речь не о том. Конструкция if (a=b()!=NULL) на самом деле замаскированное исключение. И обрабатывать его нужно как исключение.

Тот же try-except можно запихнуть в цикл.

Davidov ★★★★
()
Ответ на: комментарий от mholub

>1. try это далеко не if по производительности

Если речь действительно о производительности, я бы написал C-модуль или что-нибудь подобное.

Davidov ★★★★
()
Ответ на: комментарий от mholub

> 3. В питоне не понравилось, что часть методов зачем-то сделана функциями - пример length(string)

ООП фрики атакуют! Ну почему, ради всего святого, len() должен быть методом? Рассматривайте эту функцию как оператор, возвращающий число элементов в чем-то. Почему-то никто из вас не усирается, что 1 + 2 -- это зло и надо писать 1.add(2). Перегрузка операторов это волшебная штука.

baverman ★★★
()
Ответ на: комментарий от Hjorn

> Неконсистентные архаизмы вроде len()

Что значит неконсистентные? Чему противоречит эта функция? Можешь предложить замену?

baverman ★★★
()
Ответ на: комментарий от tailgunner

> Напиши на Питоне такое:

Я херовый прогер, в голову лезет тока такое:

(foo(x) for x in ["bar, baz"] if foo(x))

или такое:

for arg in ["bar", "baz"]:
    try:
        res = foo(arg)
        break
    except:
        continue

Впрочем, теперь я понял почему у меня все проги в циклах и
 итераторах :). Минусок питону, ждёмс когда добавят эту фичу.
Я ещё подумаю над этой задачей.

> 1) гораздо более многословный;

в свое время мне на это пол форума ответило что экономить на
буквах себе дороже :). 

> 2) при проверке многих случаев получается глубокая лестница 
(которая, кстати, противоречит смыслу программы).

Моя реализация без лестницы :).

> Что значит неконсистентные?

Автор, вероятно, имел в виду то что len() это функциональный подход.
 А в ООП вроде как сам объект и должен возвращать свою длинну, типа 
"string".len() вместо len("string"). В питоне это пофиксить раз 
плюнуть ибо Py_TypeObject содержит tp_len (названия переменных пищу 
по памяти, могу немного ошибиться) и если к PyObject прикрутить метод len()
то его все унаследуют. Почему так не сделают хз, Гвидо так 
решил :).

Теперь по руби. Так 

> угу, обычный def blablabla(param="some default value")

я имел в виду именованные аргументы :). Как я и думал про значения по 
умолчинию для именованных аргументов, рубисты юзают костыли или не юзают их вообще.

> какую функцию ты хотел передать вместо блока и в какой ситуации.

Не помню, поэтому щас настаивать не буду на этом.

true_admin ★★★★★
()
Ответ на: комментарий от tailgunner

>Выразительностью. Напиши на Питоне такое:

Исключительно истины для (руби имхо всё же выразительнее), данный пример не показателен: wc говорит 6 строк, 30 слов (считая все скобки отдельно).

В аналогичных условиях первый попавшийся приемлемый по читабельности и без убегающих отступов питонский вариант - 8 строк, и 29 слов :-0 Я удивлён, ожидалось больше, чем в рубиевском варианте.

DonkeyHot ★★★★★
()
Ответ на: комментарий от Davidov

>> Так писАть на Питоне просто невозможно.

> Речь не о том.

Речь не о том ведет кто? ;) Я - именно о том :)

> if (a=b()!=NULL) на самом деле замаскированное исключение. И обрабатывать его нужно как исключение.

Исключение - это ошибка, точка. Любой, кто использует исключения не для сигнализации об ошибках, буде гореть в аду. А в приведенном примере ошибка будет только в том случае, если все foo вернут NULL.

> Тот же try-except можно запихнуть в цикл.

Не в этом случае. Там при истинности каждого условия выполняется другой блок кода. Более-менее комактно на Питоне это записать просто нельзя.

tailgunner ★★★★★
()
Ответ на: комментарий от DonkeyHot

Как в этом форуме код вставлять в сообщения?

А вот он:
def bla():
 r = foo("bar")
 if r:
  ...
  return
 r = foo("baz")
 и т.д.

DonkeyHot ★★★★★
()
Ответ на: комментарий от true_admin

> Моя реализация без лестницы :).

Твоя реализация не решает задачиБ а именно - после каждого if следует свой блок кода, и все блоки разные.

tailgunner ★★★★★
()
Ответ на: комментарий от true_admin

>> Что значит неконсистентные?

> Автор, вероятно, имел в виду то что len() это функциональный подход. А в ООП вроде как сам объект и должен возвращать свою длинну, типа "string".len() вместо len("string"). В питоне это пофиксить раз плюнуть ибо Py_TypeObject содержит tp_len (названия переменных пищу по памяти, могу немного ошибиться) и если к PyObject прикрутить метод len() то его все унаследуют. Почему так не сделают хз, Гвидо так решил :).

"Функциональный подход" прозвучало как оскорбление :) Синтаксис вызова метода не самое главное в ООП. Можно вспомнить яву, где семантика одна (возвращение числа элементов в коллекции), а для разных объектов разные способы получения.

array.length

string.length()

collection.size()

Вот где консистентность и единообразие!

baverman ★★★
()
Ответ на: комментарий от DonkeyHot

> 6 строк, 30 слов (считая все скобки отдельно).

> 8 строк, и 29

Нихрена себе, 33% на ровном месте. Да, и где питоновский вариант?

tailgunner ★★★★★
()
Ответ на: комментарий от baverman

мне нравится кстати подход в ruby, там и length и size будут работать, а кое-где и count, зато не надо думать, блин, как же тут назвали авторы библиотеки

mholub
()
Ответ на: комментарий от tailgunner

>33% на ровном месте

Строк! Это не показательно -- для товарищей, предпочитающих '{' с новой строки это уже только N+1 на 'def' :).

DonkeyHot ★★★★★
()
Ответ на: комментарий от DonkeyHot

> Это не показательно -- для товарищей, предпочитающих '{' с новой строки

Еретиков не рассматриваем, они тоже сгорят в аду. И по-любому, это не Питон.

Где питоновский вариант без лесенки?

tailgunner ★★★★★
()
Ответ на: комментарий от mholub

> мне нравится кстати подход в ruby, там и length и size будут работать, а кое-где и count, зато не надо думать, блин, как же тут назвали авторы библиотеки

Ммм. Интересно. А можно по-подробнее, как это реализовано? Каждый класс сам определяет алиасы или в подкорке где-то зашито, что size === length?

baverman ★★★
()
Ответ на: комментарий от tailgunner

>Еретиков не рассматриваем, они тоже сгорят в аду

Есть мнение, что "длинные" строки бесчеловечны (иначе почему бы газеты печатались тонкими колонками). Следовательно длинна строки задаётся не синтаксисом, а удобством чтения, т.ч. их экономить бессмысленно. Кроме того, это не просто 33% -- а 33% от "boilerplate" -- самое интересное (то, что внутри {}) не учитывалось. Т.ч. ху новз, сколько оно на самом деле.

>И по-любому, это не Питон

А то. Иначе холивара не было бы.

>Где питоновский вариант без лесенки?

Выше.

DonkeyHot ★★★★★
()
Ответ на: комментарий от DonkeyHot

> Есть мнение, что "длинные" строки бесчеловечны (иначе почему бы газеты печатались тонкими колонками). Следовательно длинна строки задаётся не синтаксисом, а удобством чтения

Не имеет отношения к рассматриваемому вопросу.

>>Где питоновский вариант без лесенки?

>Выше.

Выше нет ни одного варианта без лесенки.

tailgunner ★★★★★
()
Ответ на: комментарий от baverman

Каждый класс руками, ибо не везде например подойдет count, но подойдет size и length.

Но это частая практика в руби алиасить многие методы, исключительно для того, чтобы лишний раз не думать, что вызвать, ну или чтобы красиво сделать. Например is_a?, is_an?

Чтобы написать что-то в духе someObject.is_an? Object, но someString.is_a? String

mholub
()
Ответ на: комментарий от DonkeyHot

>> Выше нет ни одного варианта без лесенки.

> http://www.linux.org.ru/jump-message.jsp?msgid=3516506&cid=3517634

Это недоразумение, а не вариант. Какие-то return, какая-то функция... откуда это всё, и зачем? И кстати, если блок-обработчик будет составлять 2 строки (обычное дело), оверхэд составит 100% ("r=foo()" и "return") - это без учета def для определения функции и собственно строки вызова.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>Исключение - это ошибка, точка.

NULL - это, как правило, и есть ошибка.

А такие задачи решаются созданием хеша.

{'foo' => fun1, 'bar => fun2}

И никаких лесенок. И код читаем.

BTW if ((a=b)!=NULL) во многих coding style сильно не рекомендуется. Так что пример с самого начала какой-то странный.

Davidov ★★★★
()
Ответ на: комментарий от Davidov

Программиста надо бить по пальцам, когда он весь код пытается свалить в одну кучу.

Никто не спорит, в Ruby или Perl можно написать очень компактный код, который потом никто не сможет поддерживать. Хорошо ли это?

Davidov ★★★★
()
Ответ на: комментарий от Davidov

> NULL - это, как правило, и есть ошибка.

В случае strstr - нет.

> А такие задачи решаются созданием хеша.

> {'foo' => fun1, 'bar => fun2}

> И никаких лесенок. И код читаем.

Ага, давайте создавать по функции для каждой пары строк. Нет, я не спорю, что так делать можно, но пойнт в том, что в expression-oriented языке эти трюки не нужны.

> BTW if ((a=b)!=NULL) во многих coding style сильно не рекомендуется

Я сам устанавливаю CodingStyle. Ну и не забываем бессмертное "Не держись за устав, как слепой за стену" (c) Петр I.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

>оверхэд составит 100%

Что легко компенсируется скоростью интерпретатора ruby. ;)

$ cat 1.py
def f():
  return 1+1


for i in xrange(10000000):
  f()

$ cat 1.rb 
def func
  1+1
end

10000000.times do
  func
end

$ time python 1.py 

real	0m2.320s
user	0m2.304s
sys	0m0.008s

$ time ruby 1.rb

real	0m7.293s
user	0m5.704s
sys	0m1.492s

И вообще глупости всё это.
Скриптовые языки всегда небыстры.
В 90% случаев лучше писать понятный код.
А в оставшихся 10% C-вставки/модули.

Davidov ★★★★
()
Ответ на: комментарий от Davidov

>>оверхэд составит 100%

>Что легко компенсируется скоростью интерпретатора ruby. ;)

Причем здесь вообще скорость? Оверхэд - в раздувании объема исходника, а не времени исполнения.

И причем здесь Руби? Мне на него глубоко без разницы, несмотря на то, что в нем есть симпатичные фишки %)

tailgunner ★★★★★
()
Ответ на: комментарий от Davidov

> BTW if ((a=b)!=NULL) во многих coding style сильно не рекомендуется. Так что пример с самого начала какой-то странный.

Комрады, только давайте не будем ссылаться на кодинг стайл. Приведенный пример -- это устоявшийся паттерн, читается он на ура и ошибку допустить достаточно затруднительно.

Мы должны признать, что да, питон так не умеет.

P.S. Пожалуй, только хеш может сократить питоновский код. Но это не спортивно.

baverman ★★★
()
Ответ на: комментарий от tailgunner

>Это недоразумение, а не вариант

Это недоразумение, а не аргумент. Написано именно "на питоне такое", как ты просил. Напомню, также, что в условии было "ещё много foo" -- что сводит на нет утверждение о том, что "def" лишний -- он там всё равно будет в 98% случаев "вменяемых" кодеров -- просто для того, чтобы куча if-ов не мешала читать остальной код.

>Какие-то return, какая-то функция... откуда это всё, и зачем?

Ты спрашиваешь "зачем в коде функции и зачем в них return-ы?"? Удивительно это. Естесвенно для читабельности, управляемости и лаконичности кода. Для чего же ещё?

>И кстати, если блок-обработчик будет составлять 2 строки

Пойду постучу головой об стену. Ты действительно хочешь показать, что максимальное превосходство в лаконичности руби достигает на проектах из 2х строк ? :)

Повторю ещё раз: imho ruby таки выразительнее. Вопрос в том, насколько. Мы взяли _отдельно_ одно из самых "слабых" свойств синтаксиса питона, и обнаружили, что при некоторой изобретательности отличие составляет порядка 1/30 (:причём ещё не известно в чью пользу:). Выводы?

DonkeyHot ★★★★★
()
Ответ на: комментарий от tailgunner

>В случае strstr - нет.

Ну смотря как называть ) Если str.index, то она вызывает ValueError, когда подстроки нет.

>Ага, давайте создавать по функции для каждой пары строк.

Если без фанатизма, то много маленьких функций, которые имеют понятные и логичные названия, это не так уж плохо.

>в expression-oriented языке эти трюки не нужны.

В этих языках очень сложно читать код. Сегодня провел день изучая собственную не особо сложную программу, написанную на C (с огромным количеством комментариев).

Ну на самом деле это бесконечный спор. Просто каждый ищет свой баланс выразительности/читаемости кода. Мне питон показался очень удачным решением в этой области. Особенно учитывая, что всё ресурсоёмкое можно вынести.

Davidov ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.