Что у Ruby у Python нет, и наоборот?




(25)

Существует много дискуссий о Python vs Ruby, и я все считаю их совершенно бесполезными, потому что они все обходят вокруг, почему функция X сосет язык Y, или что язык заявки Y не имеет X, хотя на самом деле это так. Я также точно знаю, почему я предпочитаю Python, но это также субъективно и не поможет никому выбирать, поскольку у них могут не быть одинаковые вкусы в развитии, как я.

Поэтому было бы интересно перечислить различия, объективно. Так что «ягнят Питона не сосет». Вместо этого объясните, что Rubber's lambdas может сделать, что Python не может. Нет субъективности. Пример кода хорош!

У вас нет нескольких отличий в одном ответе, пожалуйста. И голосуйте за те, которые, как вы знаете, правильны, и по тем, кого вы знаете, неверны (или субъективны). Кроме того, различия в синтаксисе не интересны. Мы знаем, что Python делает с отступом, что Ruby делает с помощью скобок и концов, и что @ называется self в Python.

UPDATE: теперь это вики сообщества, поэтому мы можем добавить здесь большие различия.

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

В Ruby у вас есть ссылка на класс (self) уже в классе. В Python у вас нет ссылки на класс до завершения построения класса.

Пример:

class Kaka
  puts self
end

Я в этом случае является классом, и этот код будет печатать «Кака». Невозможно распечатать имя класса или другими способами получить доступ к классу из тела определения класса в Python (определения внешних методов).

Все классы изменяются в Ruby

Это позволяет вам разрабатывать расширения для основных классов. Вот пример расширения рельсов:

class String
  def starts_with?(other)
    head = self[0, other.length]
    head == other
  end
end

Python (представьте, что не ''.startswith метода ''.startswith ):

def starts_with(s, prefix):
    return s[:len(prefix)] == prefix

Вы можете использовать его в любой последовательности (а не только в строках). Чтобы использовать его, вы должны импортировать его явно, например, from some_module import starts_with .

Ruby имеет Perl-подобные скриптовые функции

Ruby имеет первые классы регулярных выражений, $ -variables, линейный входной цикл awk / perl и другие функции, которые делают его более подходящим для написания небольших сценариев оболочки, которые обрабатывают текстовые файлы или действуют как код для других программ.

Ruby имеет первоклассные продолжения

Благодаря заявлению callcc. В Python вы можете создавать продолжения с помощью различных технологий, но поддержка языка не поддерживается.

Ruby имеет блоки

С помощью инструкции do вы можете создать многострочную анонимную функцию в Ruby, которая будет передана в качестве аргумента в метод перед do и вызывается оттуда. В Python вы должны сделать это либо путем передачи метода, либо с помощью генераторов.

Рубин:

amethod { |here|
    many=lines+of+code
    goes(here)
}

Python (блоки Ruby соответствуют различным конструкциям в Python):

with amethod() as here: # `amethod() is a context manager
    many=lines+of+code
    goes(here)

Или же

for here in amethod(): # `amethod()` is an iterable
    many=lines+of+code
    goes(here)

Или же

def function(here):
    many=lines+of+code
    goes(here)

amethod(function)     # `function` is a callback

Интересно, что оператор удобства в Ruby для вызова блока называется «yield», который в Python будет создавать генератор.

Рубин:

def themethod
    yield 5
end

themethod do |foo|
    puts foo
end

Python:

def themethod():
    yield 5

for foo in themethod():
    print foo

Хотя принципы разные, результат поразительно схож.

Ruby больше поддерживает функциональный стиль (подобное трубу)

myList.map(&:description).reject(&:empty?).join("\n")

Python:

descriptions = (f.description() for f in mylist)
"\n".join(filter(len, descriptions))

Python имеет встроенные генераторы (которые используются как блоки Ruby, как указано выше)

Python поддерживает генераторы на языке. В Ruby 1.8 вы можете использовать модуль генератора, который использует продолжения для создания генератора из блока. Или вы можете просто использовать блок / proc / lambda! Кроме того, в Ruby 1.9 Fibers есть и могут использоваться как генераторы, а класс Enumerator - это встроенный генератор 4

docs.python.org имеет этот пример генератора:

def reverse(data):
    for index in range(len(data)-1, -1, -1):
        yield data[index]

Сравните это с приведенными выше примерами блоков.

Python имеет гибкое пространство имен

В Ruby, когда вы импортируете файл с require , все вещи, определенные в этом файле, попадут в ваше глобальное пространство имен. Это вызывает загрязнение пространства имен. Решение этого - модули Rubys. Но если вы создаете пространство имен с модулем, вы должны использовать это пространство имен для доступа к содержащимся классам.

В Python файл является модулем, и вы можете импортировать содержащиеся в нем имена с помощью from themodule import * , тем самым загрязняя пространство имен, если хотите. Но вы также можете импортировать только выбранные имена с помощью имён from themodule import aname, another или же вы можете просто import themodule а затем получить доступ к именам с themodule.aname . Если вам нужно больше уровней в вашем пространстве имен, вы можете иметь пакеты, которые представляют собой каталоги с модулями и файл __init__.py .

У Python есть docstrings

Докстры являются строками, которые привязаны к модулям, функциям и методам и могут быть интродуцированы во время выполнения. Это помогает создавать такие вещи, как команда помощи и автоматическая документация.

def frobnicate(bar):
    """frobnicate takes a bar and frobnicates it

       >>> bar = Bar()
       >>> bar.is_frobnicated()
       False
       >>> frobnicate(bar)
       >>> bar.is_frobnicated()
       True
    """

Эквивалент Ruby аналогичен javadocs и расположен выше метода, а не внутри него. Они могут быть извлечены во время выполнения из файлов с использованием примера использования метода # source_location 1.9

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

Ruby не делает («специально» - см. Сайт Ruby, см. Здесь, как это делается в Ruby ). Он повторно использует концепцию модуля как тип абстрактных классов.

У Python есть списки / dict

Python:

res = [x*x for x in range(1, 10)]

Рубин:

res = (0..9).map { |x| x * x }

Python:

>>> (x*x for x in range(10))
<generator object <genexpr> at 0xb7c1ccd4>
>>> list(_)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Рубин:

p = proc { |x| x * x }
(0..9).map(&p)

Python 2.7+ :

>>> {x:str(y*y) for x,y in {1:2, 3:4}.items()}
{1: '4', 3: '16'}

Рубин:

>> Hash[{1=>2, 3=>4}.map{|x,y| [x,(y*y).to_s]}]
=> {1=>"4", 3=>"16"}

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

Вещи, похожие на декораторы, также могут быть созданы в Ruby, и также можно утверждать, что они не так необходимы, как в Python.

Синтаксические различия

Ruby требует «end» или «}», чтобы закрыть все его области, в то время как Python использует только пустое пространство. Недавно были предприняты попытки Ruby разрешить пробелы только отступы http://github.com/michaeledgar/seamless


Answers

Ruby имеет сигилы и twigils, Python этого не делает.

Редактировать : И одна очень важная вещь, которую я забыл (в конце концов, предыдущее было просто немного плакать: -p):

У Python есть JIT-компилятор ( Psyco ), зрелищный язык более низкого уровня для написания более быстрого кода ( Pyrex ) и возможность добавления встроенного кода C ++ ( Weave ).


На этом этапе Python по-прежнему имеет лучшую поддержку юникода


Я не уверен в этом, поэтому сначала добавляю его в качестве ответа.

Python рассматривает несвязанные методы как функции

Это означает, что вы можете вызвать метод как theobject.themethod()по- другому, так и по TheClass.themethod(anobject).

Изменить. Хотя разница между методами и функциями мала в Python и не существует в Python 3, она также не существует в Ruby, просто потому, что Ruby не имеет функций. Когда вы определяете функции, вы фактически определяете методы для Object.

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


Удивительно, что ничего не упоминается о механизме «метода, который отсутствует в рубине». Я приведу примеры методов find_by _... в Rails в качестве примера возможности этой языковой функции. Я предполагаю, что что-то подобное может быть реализовано на Python, но, насколько мне известно, его нет.


Бесстыдно копировать / вставлять из: Alex Martelli ответьте на вопрос « Что лучше о Ruby, чем Python » из списка рассылки comp.lang.python .

18 августа 2003, 10:50 Erik Max Francis писал (а):

«Брэндон Дж. Ван каждый» писал:

Что лучше о Ruby, чем Python? Я уверен, что есть что-то. Что это?

Разве это не имело бы смысла спрашивать людей Руби, а не людей Python?

Можете или не можете, в зависимости от ваших целей - например, если ваши цели включают в себя «социологическое исследование» сообщества Python, то вопросы, задаваемые этим сообществом, скорее всего, окажут больше информации об этом, чем помещают их в другое место :-).

Лично я с удовольствием воспользовался возможностью следовать однодневному учебнику Ruby от Dave Thomas, наконец, OSCON. Ниже тонкого шпона различий синтаксиса я нахожу Ruby и Python удивительно похожими - если бы я вычислял минимальное связующее дерево среди любого набора языков, я уверен, что Python и Ruby будут первыми двумя листами, чтобы объединиться в промежуточный узел :-).

Конечно, я устал, в Ruby, набирать глупый «конец» в конце каждого блока (а не просто отчуждать), - но тогда я действительно избегаю вводить одинаково-глупый «:», который требует Python на начало каждого блока, так что почти мыть :-). Другие различия в синтаксисе, такие как «@foo» и «self.foo», или более высокое значение случая в Ruby vs Python, на самом деле почти так же не имеют значения для меня.

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

Редактировать (от AM 6/19/2010 11:45): это также называется «покраска велосипеда» (или, короче говоря, «bikeshedding») - ссылка снова на Northcote Parkinson, который дал «дебаты» на каком цвете нарисовать bikeshed «как типичный пример« горячих дебатов по тривиальным темам ». (конец из-Edit).

Одна разница в синтаксисе, которую я действительно нахожу важной, и в пользу Python, - но другие люди, без сомнения, будут думать, что обратное - это «как вы называете функцию, которая не принимает параметров». В Python (например, в C) для вызова функции вы всегда применяете «оператор вызова» - конечные скобки сразу после объекта, который вы вызываете (внутри этих скользящих скобок идут аргументы, которые вы передаете в вызове - если вы не передаете args, тогда скобки пусты). Это оставляет простое упоминание о любыхобъект без участия оператора, что означает просто ссылку на объект - в любом контексте, без особых случаев, исключений, специальных правил и т. п. В Ruby (например, в Pascal) для вызова функции WITH аргументы вы передаете args (обычно в круглых скобках, хотя это не всегда так) - НО, если функция не принимает аргументов, то просто упоминание функции неявно вызывает ее. Это может оправдать ожидания многих людей (по крайней мере, без сомнения, тех, чей только предыдущий опыт программирования был с Pascal или другими языками с похожими «неявными вызовами», такими как Visual Basic), но для меня это означает, что простое упоминание объекта может означать ссылку на объект, ИЛИ вызов объекта, в зависимости от типа объекта, - и в тех случаях, когда я могу "t получить ссылку на объект, просто отметив его, мне нужно будет использовать явное «дайте мне ссылку на это, НЕ НАЗЫВАЙТЕ!» операторам, которые в противном случае не нужны. Я чувствую, что это влияет на «первоклассность» функций (или методов или других вызываемых объектов) и возможность беспрепятственного обмена объектами. Поэтому для меня эта специфическая синтаксическая разница является серьезной черной меткой против Ruby, но я понимаю, почему другие могли бы быть в противном случае, хотя я вряд ли мог с большей ясностью не согласиться с ними :-).Поэтому для меня эта специфическая синтаксическая разница является серьезной черной меткой против Ruby, но я понимаю, почему другие могли бы быть в противном случае, хотя я вряд ли мог с большей ясностью не согласиться с ними :-).Поэтому для меня эта специфическая синтаксическая разница является серьезной черной меткой против Ruby, но я понимаю, почему другие могли бы быть в противном случае, хотя я вряд ли мог с большей ясностью не согласиться с ними :-).

Ниже синтаксиса мы рассмотрим некоторые важные отличия в элементарной семантике - например, строки в Ruby являются изменяемыми объектами (например, на C ++), тогда как в Python они не изменяемы (как в Java, или я считаю C #). Опять же, люди, которые в основном судить по тому, что они уже знакомы, могут подумать, что это плюс для Ruby (если они не знакомы с Java или C #, конечно :-). Я думаю, что неизменяемые строки - отличная идея (и я не удивлен, что Java, независимо от того, я думаю, заново изобрел эту идею, которая уже была на Python), хотя я бы тоже не хотел иметь тип «изменяемого строкового буфера» (и, в идеале, с лучшей простотой использования, чем собственные «строковые буферы» Java); и я не даю этого решения из-за знакомства - перед изучением Java,кроме функциональных языков программирования, где вседанные неизменны, все языки, о которых я знал, имеют изменяемые строки, но когда я впервые увидел идею неизменяемой строки на Java (которую я узнал задолго до того, как узнал Python), она сразу же показала мне отличную, очень хорошую форму для эталон-семантика языка программирования более высокого уровня (в отличие от семантики значения, которая лучше всего подходит для языков, расположенных ближе к машине, и дальше от приложений, таких как C) со строками как первоклассный, встроенный (и довольно важный ) тип данных.

Ruby имеет некоторые преимущества в элементарной семантике - например, удаление списков Python vs tuples - чрезвычайно тонкое различие. Но в основном оценка (как я ее сохраняю, с простотой большой плюс и тонкие, умные различия заметный минус) против Ruby (например, с закрытыми и полуоткрытыми интервалами с обозначениями a..b и a .. .b [Кто-то хочет утверждать, что это очевидно, что есть? -)], глупо - ИМХО, конечно!). Опять же, люди, которые считают, что есть много похожих, но тонко разных вещей, лежащих в основе языка, PLUS, а не MINUS, конечно, посчитают это «по-другому» из того, как я их считаю :-).

Не смешивайте эти сравнения с мыслью о том, что два языка оченьразные, заметьте. Это не так. Но если меня попросят сравнить «capelli d'angelo» с «спагеттини», указав, что эти два вида макаронных изделий почти не отличимы ни для кого и взаимозаменяемы в любом блюде, которое вы, возможно, захотите подготовить, я тогда неизбежно имел бы перейти к микроскопическому исследованию того, как длины и диаметры незаметно различаются, как концы нитей сужаются в одном случае, а не в другом, и т. д. - чтобы попытаться объяснить, почему я лично предпочитаю капелли «angelo как макароны в любом виде бульона, но предпочел бы спагеттини, как pastasciutta, чтобы пойти с подходящими соусами для таких длинных тонких форм макаронных изделий (оливковое масло, измельченный чеснок, фарш красного перца и мелко измельченные анчоусы,например, но если вы нарезали чеснок и перцы, а не измельчали ​​их, тогда вы должны выбрать эхолот тела спагетти, а не более тонкое исчезновение спагеттини, и было бы рекомендовано отказаться от аховий и добавить вместо этого свежий весенний базилик [ или даже - я еретик ...! - легкая мята ...] уходит - в самый последний момент перед подачей блюда). Ой, извините, это показывает, что я выезжаю за границу и не имею пасты на некоторое время, я думаю. Но аналогия по-прежнему очень хорошая! -)это показывает, что я выезжаю за границу и не имею пасты на некоторое время, я думаю. Но аналогия по-прежнему очень хорошая! -)это показывает, что я выезжаю за границу и не имею пасты на некоторое время, я думаю. Но аналогия по-прежнему очень хорошая! -)

Итак, вернемся к Python и Ruby, мы подошли к двум крупным (с точки зрения языка - оставив библиотеки и другие важные вспомогательные средства, такие как инструменты и среды, как встраивать / расширять каждый язык и т. Д. И т. Д. Из на данный момент - они не будут применяться ко всем РЕАЛИЗАЦИЯМ каждого языка в любом случае, например, Jython vs Classic Python является двумя реализациями языка Python!):

  1. Итераторы Ruby и кодовые блоки против итераторов и генераторов Python;

  2. Ruby's TOTAL, необузданная «динамичность», в том числе возможность
    «вновь открыть» любой существующий класс, включая все встроенные, и изменить его поведение во время выполнения - на огромную, но ограниченную динамичность Python , которая никогда не изменяет поведение существующих встроенные классы и их экземпляры.

Лично я считаю , 1 мойку (различия настолько глубоки , что я мог легко видеть , что человек ненавидящих любого подход и чтя другие, но на моих личных масштабах , плюсы и минусы как раз о даже вверх); и 2 - важная проблема, которая делает Ruby гораздо более подходящим для «мастеринга», но Python в равной степени более подходит для использования в крупных производственных приложениях. Это смешно, в некотором роде, потому что оба языка настолько БОЛЬШЕ динамичнее, чем большинство других, что в конечном итоге ключевое различие между ними от моего POV должно зависеть от этого - этот Ruby «пойдет одиннадцать» в этом отношении (ссылка вот, конечно, «Спинной кран»). В Ruby нет никаких ограничений для моего творчества - если я решаю, что все сопоставления строк должны быть нечувствительны к регистру,Я МОГУ СДЕЛАТЬ ЭТО! Т.е. я могу динамически изменять встроенный строковый класс, так что a = «Hello World» b = «hello world», если == b print «equal! \ N» else print «different! \ N» end WILL print " равный». В python нет способа, которым я могу это сделать. Для целей метапрограммирования, реализации экспериментальных рамок и т. П. Эта удивительная динамическая способность Ruby чрезвычайнопривлекательным. НО - если мы говорим о больших приложениях, разработанных многими людьми и поддерживаемых еще больше, включая всевозможные библиотеки из разных источников и нуждающихся в производстве на клиентских сайтах ... ну, я НЕ ХОЧУ язык, который является QUIT так динамичным, большое вам спасибо. Я ненавижу саму идею о том, что какая-то библиотека невольно нарушает другие несвязанные, которые полагаются на то, что эти строки отличаются друг от друга - вот такой глубокий и глубоко скрытый «канал», между фрагментами кода, которые LOOK раздельны и ДОЛЖНЫ БЫТЬ отдельными, что говорит о смерти в крупномасштабное программирование. Позволяя любому модулю влиять на поведение любого другого «скрытого», способность мутировать семантику встроенных типов - это просто идея BAD для программирования приложений производства, так же, как это здорово для мастеринга.

Если бы мне пришлось использовать Ruby для такого большого приложения, я бы постарался полагаться на ограничения стиля кодирования, множество тестов (чтобы быть повторенными всякий раз, когда НИЧЕГО изменялось - даже то, что должно быть абсолютно не связанным ...) и тому подобное, запретить использование этой языковой функции. Но НЕ иметь эту функцию в первую очередь еще лучше, на мой взгляд, так же, как сам Python был бы еще лучшим языком для программирования приложений, если бы определенное количество встроенных модулей могло быть «прибито», поэтому я ЗНАЛ, что , например, len («ciao») составляет 4 (вместо того, чтобы сублиминально беспокоиться о том, изменил ли кто-то привязку имени «len» в модуле встроенных модулей ...). Надеюсь, что в конечном итоге Python «пригвоздит» свои встроенные модули.

Но проблема несовершенна, так как восстановление встроенных модулей довольно устарело, а также редкая практика в Python. В Ruby это выглядит как майора - точно так же, как слишком мощные макроустройства других языков (например, Дилан) представляют собой подобные риски по моему мнению (я надеюсь, что Python никогда не получит такую ​​мощную макросистему, no важно, чтобы «позволяли людям определять свои собственные языки, специфичные для домена», встроенные в сам язык »- это было бы, ИМХО, нарушало бы замечательную полезность Python для прикладного программирования, представляя« привлекательную неприятность »потенциальному возиться, который скрывается в сердце каждого программиста ...).

Alex


Ruby имеет линейный цикл над входными файлами (флаг «-n») из командной строки, поэтому его можно использовать как AWK. Этот однострочный слой Ruby:

ruby -ne 'END {puts $.}'

будет подсчитывать линии, такие как односторонний AWK:

awk 'END{print NR}'

Ruby получает эту возможность через Perl, которая взяла его с AWK как способ получить системных администраторов на борту с Perl, не изменяя способ их выполнения.


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

Мне нравится синтаксис Python. Однако вам нужно копать немного глубже синтаксиса, чтобы найти истинную красоту Ruby. В консистенции Руби есть зенитная красота. Хотя ни один простой пример не может объяснить это полностью, я попытаюсь придумать это здесь, чтобы объяснить, что я имею в виду.

Переверните слова в этой строке:

sentence = "backwards is sentence This"

Когда вы подумаете о том, как вы это сделаете, вы бы сделали следующее:

  1. Разделить предложение на слова
  2. Переверните слова
  3. Повторно присоединить слова к строке

В Ruby вы сделали бы это:

sentence.split.reverse.join ' '

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

В python это выглядело бы следующим образом:

" ".join(reversed(sentence.split()))

Это не сложно понять, но у него совсем нет такого же потока. Предмет (предложение) похоронен посередине. Операции представляют собой сочетание функций и методов объектов. Это тривиальный пример, но вы обнаружите много разных примеров, когда действительно работаете с Ruby и понимаете Ruby, особенно по нетривиальным задачам.


Вы можете импортировать только определенные функции из модуля в Python. В Ruby вы импортируете весь список методов. Вы могли бы «unimport» их в Ruby, но это не то, о чем все.

РЕДАКТИРОВАТЬ:

давайте возьмем этот модуль Ruby:


module Whatever
  def method1
  end

  def method2
  end
end

если вы включите его в свой код:


include Whatever

вы увидите, что оба метода1 и метод2 добавлены в ваше пространство имен. Вы не можете импортировать только метод1 . Вы либо импортируете их обоих, либо не импортируете их вообще. В Python вы можете импортировать только методы по вашему выбору. Если бы это имело название, возможно, это было бы названо выборочным импортом?


Я хотел бы упомянуть API-интерфейс дескриптора Python, который позволяет настраивать «связь» объекта с атрибутом. Также следует отметить, что в Python можно свободно реализовать альтернативный протокол, переопределив значение по умолчанию, заданное при реализации __getattribute__метода по умолчанию . Позвольте мне подробнее рассказать об упомянутом выше. Дескрипторы регулярные занятия с __get__, __set__и / или __delete__методов. Когда интерпретатор сталкивается с чем-то вроде anObj.anAttr, выполняется следующее:

  • __getattribute__метод anObjвызова
  • __getattribute__ извлекает объект attr из класса dict
  • он проверяет , имеет ли объект abAttr __get__, __set__или __delete__вызываемые объекты
  • контекст (т. е. объект или класс вызывающего объекта, а значение, а не последнее, если у нас есть сеттер) передается вызываемому объекту
  • результат возвращается.

Как уже упоминалось, это поведение по умолчанию. Один из них может изменить протокол путем повторной реализации __getattribute__.

Этот метод намного эффективнее декораторов.


Несколько больше на стороне инфраструктуры:

  • Python имеет гораздо лучшую интеграцию с C ++ (через такие вещи, как Boost.Python , SIP и Py++ ), чем Ruby, где параметры, похоже, либо напрямую записываются в API-интерфейс Ruby-интерпретатора (что вы также можете сделать с Python, но в обоих случаях это низкий уровень, утомительный и подверженный ошибкам) ​​или использовать SWIG (который, хотя он работает и определенно велик, если вы хотите поддерживать многие языки, не так хорош, как Boost.Python или SIP, если вы специально хотите связать C ++).

  • В Python есть несколько сред веб-приложений (Django, Pylons / Turbogears, web.py, возможно, по крайней мере, полдюжины других), тогда как Ruby (эффективно) имеет один: Rails. (Другие веб-фреймворки Ruby действительно существуют, но, похоже, с трудом справляются с Rails). Является ли этот аспект хорошим или плохим? Трудно сказать и, вероятно, вполне субъективно; Я легко могу представить аргументы, что ситуация на Python лучше и что ситуация с Ruby лучше.

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


Ruby имеет встроенную документацию:

 =begin

 You could use rdoc to generate man pages from this documentation

 =end

Пример Python

Функции - это первообразные переменные в Python. Вы можете объявить функцию, передать ее как объект и перезаписать ее:

def func(): print "hello"
def another_func(f): f()
another_func(func)

def func2(): print "goodbye"
func = func2

Это фундаментальная особенность современных языков сценариев. JavaScript и Lua делают это тоже. Ruby не обрабатывает функции таким образом; Именование функции вызывает его.

Конечно, есть способы сделать это в Ruby, но они не являются первоклассными операциями. Например, вы можете обернуть функцию с помощью Proc.new, чтобы рассматривать ее как переменную - но тогда она больше не является функцией; это объект с методом «вызова».

Функции Ruby не являются первоклассными объектами

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

def func; p "Hello" end
def another_func(f); method(f)[] end
another_func(:func)      # => "Hello"

def func2; print "Goodbye!"
self.class.send(:define_method, :func, method(:func2))
func                     # => "Goodbye!"

method(:func).owner      # => Object
func                     # => "Goodbye!"
self.func                # => "Goodbye!"    

Мой python ржавый, поэтому некоторые из них могут быть на питоне, и я просто не помню / никогда не учился в первую очередь, но вот первые несколько, о которых я думал:

Пробелы

Рубины обрабатывают пробелы совершенно разные. Для начала вам не нужно ничего отступать (это означает, что не имеет значения, используете ли вы 4 пробела или 1 вкладку). Это также делает интеллектуальное продолжение линии, поэтому справедливо следующее:

def foo(bar,
        cow)

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

Примеси

Ruby имеет mixins, который может расширять экземпляры вместо полных классов:

module Humor
  def tickle
    "hee, hee!"
  end
end
a = "Grouchy"
a.extend Humor
a.tickle    »   "hee, hee!"

Перечисления

Я не уверен, что это то же самое, что и генераторы, но с Ruby 1.9 ruby ​​в качестве перечислений, поэтому

>> enum = (1..4).to_enum
=> #<Enumerator:0x1344a8>

Ссылка: http://blog.nuclearsquid.com/writings/ruby-1-9-what-s-new-what-s-changed

«Аргументы ключевого слова»

Оба перечисленных там элемента поддерживаются в Ruby, хотя вы не можете пропустить значения по умолчанию, подобные этому. Вы можете либо пойти в порядок

def foo(a, b=2, c=3)
  puts "#{a}, #{b}, #{c}"
end
foo(1,3)   >> 1, 3, 3
foo(1,c=5) >> 1, 5, 3
c          >> 5

Обратите внимание, что c = 5 фактически присваивает переменной c в области вызова значение 5 и устанавливает параметр b значением 5.

или вы можете сделать это с помощью хэшей, которые обращаются ко второй проблеме

def foo(a, others)
  others[:b] = 2 unless others.include?(:b)
  others[:c] = 3 unless others.include?(:c)
  puts "#{a}, #{others[:b]}, #{others[:c]}"
end
foo(1,:b=>3) >> 1, 3, 3
foo(1,:c=>5) >> 1, 2, 5

Ссылка: Руководство прагматического прогмера по рубину



Я не думаю, что «Ruby имеет X, а Python этого не делает, в то время как Python имеет Y, а Ruby не является« самым полезным способом взглянуть на него ». Это довольно схожие языки, с множеством общих способностей.

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


python имеет необязательные аргументы

def func(a, b=2, c=3):
    print a, b, c

>>> func(1)
1 2 3
>>> func(1, c=4)
1 2 4

AFAIK Ruby имеет только позиционные аргументы, потому что b = 2 в объявлении функции - это аффектация, которая всегда добавляется.


Я хотел бы предложить вариант исходного вопроса: «Что у Ruby есть, что Python не делает, и наоборот?» который признает неутешительный ответ: «Ну, что вы можете сделать с Ruby или Python, которые нельзя сделать в Intercal?» Ничего на этом уровне, потому что Python и Ruby являются частью огромной королевской семьи, сидящей на троне как аппроксимация Тьюринга.

Но как насчет этого:

Что можно сделать изящно и хорошо на Python, чего нельзя сделать в Ruby с такой красотой и хорошей инженерией, или наоборот?

Это может быть гораздо интереснее, чем просто сравнение функций.


Некоторые другие:

website

(Если я неправильно понял что-либо или что-то изменилось на стороне Ruby, так как эта страница была обновлена, кто-то может отредактировать ...)

Строки изменяются в Ruby, а не в Python (где новые строки создаются с помощью «изменений»).

Ruby имеет некоторые принудительные условные обозначения, Python этого не делает.

Python имеет как списки, так и кортежи (неизменные списки). Ruby имеет массивы, соответствующие спискам Python, но нет неизменяемого варианта.

В Python вы можете напрямую обращаться к атрибутам объекта. В Ruby это всегда с помощью методов.

В Ruby круглые скобки для вызовов методов обычно являются необязательными, но не в Python.

Ruby имеет открытый, закрытый и защищенный для обеспечения доступа, вместо соглашения Python об использовании символов подчеркивания и имени.

Python имеет множественное наследование. У Ruby есть «mixins».

И еще одна очень важная ссылка:

http://c2.com/cgi/wiki?PythonVsRuby

Который, в частности, ссылки на другой хороший Алекс Мартелли , который также размещал много хорошего здесь на SO:

http://groups.google.com/group/comp.lang.python/msg/028422d707512283


Ruby имеет встроенную поддержку продолжения использования callcc.

Следовательно, вы можете реализовать классные вещи, такие как amb-operator


Еще одно отличие в лямбдах между Python и Ruby продемонстрировано проблемой генератора Накопителя Пола Грэма . Перепечатано здесь:

Напишите функцию foo, которая принимает число n и возвращает функцию, которая принимает число i, и возвращает n, увеличиваемое на i. Примечание: (a) это число, а не целое число, (b), которое увеличивается, а не плюс.

В Ruby вы можете сделать это:

def foo(n)
  lambda {|i| n += i }
end

В Python вы создадите объект для хранения состояния n:

class foo(object):
    def __init__(self, n):
        self.n = n
    def __call__(self, i):
        self.n += i
        return self.n

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


В Ruby, когда вы импортируете файл с требованием, все вещи, определенные в этом файле, попадут в ваше глобальное пространство имен.

С Cargo вы можете « требовать библиотеки, не загромождая пространство имен ».

# foo-1.0.0.rb
class Foo
  VERSION = "1.0.0"
end

# foo-2.0.0.rb
class Foo
  VERSION = "2.0.0"
end
>> Foo1 = import("foo-1.0.0")
>> Foo2 = import("foo-2.0.0")
>> Foo1::VERSION
=> "1.0.0"
>> Foo2::VERSION
=> "2.0.0"

Ruby имеет понятия блоков , которые по сути являются синтаксическим сахаром вокруг раздела кода; они являются способом создания замыканий и передачи их другому методу, который может или не может использовать блок. Блок может быть вызван позже через инструкцию yield .

Например, простое определение each метода в Array может быть примерно таким:

class Array
  def each
    for i in self  
      yield(i)     # If a block has been passed, control will be passed here.
    end  
  end  
end  

Затем вы можете вызвать это так:

# Add five to each element.
[1, 2, 3, 4].each{ |e| puts e + 5 }
> [6, 7, 8, 9]

У Python есть анонимные функции / закрытие / lambdas, но у него нет блоков, поскольку отсутствует какой-то полезный синтаксический сахар. Тем не менее, есть хотя бы один способ получить его в режиме ad-hoc. См., Например, here .


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

Например, Ruby:

>> PI = 3.14
=> 3.14
>> PI += 1
(irb):2: warning: already initialized constant PI
=> 4.14

Python:

>>> PI = 3.14
>>> PI += 1
>>> PI
4.1400000000000006

Вы можете иметь код в определении класса в Ruby и Python. Однако в Ruby у вас есть ссылка на класс (self). В Python у вас нет ссылки на класс, так как класс еще не определен.

Пример:

class Kaka
  puts self
end

Я в этом случае является классом, и этот код будет печатать «Кака». Невозможно напечатать имя класса или другими способами получить доступ к классу из тела определения класса в Python.


Давайте рассмотрим ответ более абстрактным образом:

Предположим, что мы имеем этот код в x.py:

...
<Block A>
if __name__ == '__main__':
    <Block B>
...

Блоки A и B запускаются, когда мы запускаем «x.py».

Но только блок A (а не B) запускается, когда мы запускаем другой модуль, например «y.py», в котором xy импортируется и код запускается оттуда (например, когда функция в «x.py» вызывается из y.py).





python ruby