Что есть в Ruby, чего нет в Python, и наоборот?

| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |

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

Поэтому это было бы было бы интересно объективно перечислить различия. Так что никакие лямбды "Python" не отстой". Вместо этого объясните, что лямбда-выражения Ruby могут делать, а Python — нет. Никакой субъективности. Пример кода хорош!

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

ОБНОВЛЕНИЕ: теперь это вики сообщества, поэтому мы можем добавить сюда большие различия.

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

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

Пример:

класс Кака ставит себя в конец 

self в этом случае является классом, и этот код выведет "Kaka". Невозможно распечатать имя класса или получить доступ к классу другими способами из тела определения класса в Python (вне определения методов).

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

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

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

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

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

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

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

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

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

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

В Ruby есть блоки

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

Ruby:

amethod { |here| many=lines+of+code идет (здесь) } 

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

с amethod() как здесь: # `amethod() - это контекстный менеджер, который много=строк+из+кода идет(здесь) 

Или

для здесь в amethod() : # `amethod()` - это итерируемая функция many=lines+of+code (здесь) 

Или

def (здесь): many =lines+of+code идет(здесь) amethod(function) # `функция` является обратным вызовом 

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

Ruby:

def themethod yield 5 end themethod do |foo| помещает конец foo 

Python:

def themethod(): yield 5 for foo in themethod(): print foo 

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

Ruby легче поддерживает программирование в функциональном стиле (конвейере)

myList.map(& :description).reject(&:пусто?).join(" ") 

Python:

descriptions = (f.description() для f в моем списке) " ".join(filter(len, descriptions)) 

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

Python поддерживает генераторы на языке. В Ruby 1.8 вы можете использовать модуль генератора, который использует продолжения для создания генератора из блока. Или вы можете просто использовать блок/прок/лямбда! Более того, в Ruby 1.9 волокна являются генераторами и могут использоваться как генераторы, а класс 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 файл является модулем, и вы можете импортировать содержащиеся в нем имена с помощью из импорта модуля *, тем самым загрязняя пространство имен, если хотите. Но вы также можете импортировать только выбранные имена с помощью из модуля импортировать имя, другое или вы можете просто импортировать модуль, а затем получить доступ к именам с помощью themodule.aname. Если вы хотите больше уровней в своем пространстве имен, вы можете иметь пакеты, которые представляют собой каталоги с модулями и файлом __init__.py.

Python имеет строки документации

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

def frobnicate(bar): """frobnicate берет панель и обрабатывает ее >>> bar = Bar( ) >>> bar.is_frobnicated() False >>> frobnicate(bar) >>> bar.is_frobnicated() True """ 

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

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

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

Python поддерживает списки и слова

Python:

res = [x* x для x в диапазоне (1, 10)] 

Ruby:

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

Python:

>>> (x*x для x в диапазоне (10)) <объект генератора <genexpr> по адресу 0xb7c1ccd4> >>> list(_) [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 

Ruby:

p = процесс { | х | x * x } (0..9).map(&p) 

Python 2.7+:

> ;>> {x:str(y*y) для x,y в {1:2, 3:4}.items()} {1: "4", 3: "16"} 

Рубин:

>> Хэш[{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