Есть много дискуссий о 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