Python против Ruby

В статье "Python vs Ruby" автор рассматривает отличительные особенности двух языков программирования. Автор: Lennart Regebro

Я вижу, как люди, использующие Ruby, сильно критикуют Python на Stackoverflow. Это немного грустно, потому что Python и Ruby обычно самые лучшие друзья. Итак, я хотел бы поговорить не о том, кто из них лучший, а о том, каковы объективные различия.

Найти эту объективность было труднее, чем я думал, но я многому научился. И, как и предполагалось, многие из различий являются лишь семантическими, как например Ruby использует атрибут @, а Python атрибут self. И конечно объективно невозможно ответить, какой язык лучше, наверное, тот, который больше Вам знаком. И это не удивительно. А удивительно то, что существует немного различий, которые могут характеризовать тот или иной язык как лучший или худший. Даже те особенности языка, которые, казалось, "объективно хороши", в большинстве случаев оказываются делом вкуса.

Вот различия, которые я смог найти, и которые можно объективно назвать отличительными:

1. Ruby имеет ссылку на класс в теле класс

Это означает, что возможен следующий код:

class MyClass
    initialize_magick()
end

Тогда как в Python вы должны написать:

class MyClass:
    pass
initialize_macgick(MyClass)

Как Вы видите, практическое различие очень небольшое. Но вариант Ruby проще для понимания, поскольку «магия» заключается в определении класса, и смотря на класс, вы видите, что это выполняется. И действительно компонентная архитектура Zope  использует некоторую «тяжелую магию» с метаклассами, чтобы сделать то же самое в Python:

def MyClass:
    implements(IMyInterface)

Так что получить тот же самый эффект можно (В Python 2) с помощью нескольких умных уловок. В Python 3 нельзя, но не, потому что отличается синтаксис метакласса, а поэтому что в Python 3 вы вместо этого должны использовать декораторы. И что вы думаете проще

@magickly_initialized
def MyClass:
    pass

или

def MyClass
    initialize_magick()
end

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

2. Ruby имеет continuations

Continuations - это «тяжелая магия». У Ruby они есть, а у Python нет. Вы можете "подделать" их, и, кажется, что многие из случаев употребления могут быть заменены с помощью ввода переменных в .next (), это вы можете сделать в Python 3.1. Использование Continuations кажется скорее ограниченным, и трудно поддающимся пониманию, но это есть как в Ruby, так и в Python. Так что еще один плюс для Ruby.

3. Python имеет генераторы

Вы можете подделать их в Ruby с помощью блоков или  Continuations. Поэтому снова небольшое преимущество, но так или иначе небольшой плюс для Python , поскольку генераторы Python являются и простыми и понятными.

4. Python имеет множественное наследование

Некоторые люди утверждают, что множественное наследование является злом. Но его наличие означает, что, если вы считаете это злом, то не пользуйтесь им. Я много раз пользовался им, и никогда не встречал никаких проблем, но я думаю, что адаптация - лучший образец. Однако, весьма очевидно, что это плюс для Python.

5. Python имеет docstrings

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

Иии..., вот и все!

Эти пять небольших отличий являются единственными объективными улучшениями, которые я смог увидеть, по отношению к другому языку. И как Вы видите, ни одно из них не является действительно значимым. Это лишь мелкие детали, от которых зависит только удобство работы. Итак, не перейти ли мне на Ruby прямо сейчас, когда я знаю, что он почти также хорош? Нет. Поскольку есть много других различий, различий в подходах и семантике. И к тому же мне больше нравится Python. Вот три основных функции Ruby, которые, по моему мнению, являются, либо непредусмотренными, либо не имеющими большого значения:

1. Ruby имеет встроенный regexp и line input looping

Язык Perl позволяет написать скрипт, который просматривает текстовые файлы построчно. В большинстве случаев это чрезвычайно полезно. Также Ruby, как говорят, лучше пишет glue.scripts, так что он больше подходит для замены shell-скрипта чем Python. Плюс для Ruby? Нет, только не для меня. Я это иногда делаю, главным образом в awk. Если они становятся более сложными, то я предпочитаю использовать ясность Python, чем неясность regexps. И иметь небольшой open(filename).readlines () не является столь уж большой проблемой. Так что я думаю, что эта функция лишь добавляет суеты, и я рад, что ее нет в Python. Ничего себе! Это превратилось уже в субъективную проблему! Меня это удивило.

2. Ruby защищает атрибуты класса и т.д.

Ruby рассматривает имена переменных, первая буква которых заглавная, как константы, поэтому вы не можете изменить их. Python не защищает ваш код от других программистов. Если они захотят создать вам проблем, они смогут это сделать. Мне это нравится. Я вспоминаю, когда я использовал Delphi, и мне надо было переместить в подкласс объект в стандартную библиотеку, а некоторые атрибуты или методы были защищены, то я не мог это сделать. Мне пришлось прекратить дублирование почти целого класса компонентов (или большинство) в мой подкласс, только потому, что разработчик основного класса не предусмотрел мой тип или требование. Так что такой вид защиты обычно является лишь проблемой. Таких проблем меньше в Ruby, поскольку он позволяет вам добавлять класс, но это еще большой плюс для Python по моему мнению. Я уверен, что люди, пользующиеся Ruby, не согласятся со мной. И это снова субъективно.

3. Ruby имеет блоки

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

Блоки Rubys широко пропагандировались (приверженцами Ruby) как нечто фантастическое по сравнению с Python. Но оказалось очень трудным найти случаи, когда Ruby действительно делал что-то чище, чем Python благодаря блокам. Ок, но оказывается, что в Python тоже есть блоки. Но их называют "функциями". В чем различие? Функции необходимо названии, а блокам нет. На этот счет программист Python сказал бы “Ага, так что блоки это лямбды!” Да, за исключением того, что блоки могут быть многострочным кодом и выполнять все, в то время как  лямбды Python должны быть выражениями.

OK, итак один плюс Ruby? Нет. Поскольку, какая польза от блока, если вы не прикрепляете его к имени переменной, так чтобы можно было вызвать его? В Ruby вы создаете блоки и используете их непосредственно вот так:

amethod do |variable|
    print variable
end

Это в основном как у Python

def theblock(variable)
    print variable
amethod(theblock)

Который конечно выполняется также и в Ruby. Какой способ аккуратнее? И снова это дело вкуса. Становится еще труднее принять решение, если учесть, что Ruby имеет специальное утверждение для вызова блока с параметрами. Он называется yield. Yield также присутствует и в Python, но там он используется для генераторов. Но мы получаем эти примеры кода:

def themethod
    for a in [1,2,3,4,5]
        yield a
    end
end

themethod do |b|
   puts b
end

Которые подозрительно похожи на

def themethod():
    for a in [1,2,3,4,5]:
        yield a

for b in themethod():
    print b

Поэтому, в конечном счете, можно сказать, что этот хваленый принцип блоков кажется очень редко в действительности приводит к какому-либо значительно отличающемуся от Python коду. Так что эти широко обсуждаемые различия в принципах в конечном итоге … являются (почти) одинаковыми!

4. Python легко работает со списками

Здесь стоит упомянуть, что у Python есть несколько важных функций, которых нет у Ruby, как например легкость работы со списками.

[foo(x) for x in alist if bar(x) != 'frotz']

Но хотя я пользуюсь ими все время, потому что они практичны, я не знаю, что я о них думаю. Ок, это короче чем:

foo = []
for x in alist:
   if bar(x) != 'frotz':
      foo.append(x)

Но действительно ли это чище и удобнее для чтения? Я не уверен. Это снова становится вопросом вкуса . Мне не понравились list comprehensions, когда они впервые появились в Python, но конечно теперь я стал пользоваться ими. Так что это не очень хороший аргумент в пользу Python. И это снова субъективно.

5. Python имеет декораторы

Декораторы интереснее, чем другие способы сделать то же самое в Python, например вышеупомянутый initialize_magick (класс). Но опять-таки можно утверждать, что синтаксис @decorator лишь делает Python уродливым, и они вам не настолько нужны в Ruby. И снова это дело вкуса.

Итак, почему Python?

Итак, в конце концов, почему я субъективно предпочитаю практически во всем Python, а не Ruby? За ясность и простоту Python, за его принципы и подходы. В Ruby можно расширить любой класс. В Python, вы можете «примешивать» расширения в любой класс. В чем разница? В Python это является уродливым подходом, и его осуждают. В Ruby, многие примеры кода расширяют класс Array.

В Ruby, нет функций, но есть методы, блоки и лямбды. Все из них, кажется, имеют незначительные  различия, а иногда необходимо вызывать функцию по имени, а иногда, используя функцию call(). В Python, есть только функции. Лямбды являются функциями whose __name__ is <lambda>. Методы являются функциями, которые направлены на то, что вам не придется обходиться самостоятельно. Просто и ясно.

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

Пакеты и модули Python намного лучше для пространства имен, чем модули Ruby. Снова субъективно. И вы можете выбирать, хотите ли вы импортировать в Python или нет. В Ruby это все, что вы можете сделать

И все это то, что заставляют меня говорить “Ээээ… ” о Ruby и “Да! ” в отношении Python, который отличается не конкретными функциями, а лишь субъективными опциями семантики языка и подходами. Действительно верно, что ни один из Языков не является лучше другого.


Оригинал статьи на regebro.wordpress.com

Перевод ООО «Комтет» komtet.ru

Вам также может помочь