Существует много дискуссий о Python против Ruby, и я все считаю их совершенно бесполезными, потому что они все обходят вокруг, почему функция X отстой в языке Y, или что язык заявки Y не имеет X, хотя на самом деле это делает. Я также точно знаю, почему я предпочитаю Python, но это также субъективно и не поможет никому выбирать, поскольку они могут не иметь одинаковых вкусов в развитии, как я.
Поэтому было бы интересно перечислить различия, объективно. Так что нет "Python lambdas sucks". Вместо этого объясните, что Ruby lambdas может сделать, что Python не может. Нет субъективности. Пример кода хорош!
У вас нет нескольких отличий в одном ответе, пожалуйста. И голосуйте за те, которые, как вы знаете, правильны, и по тем, кого вы знаете, неверны (или субъективны). Кроме того, различия в синтаксисе не интересны. Мы знаем, что Python делает с отступом то, что Ruby делает с помощью скобок и концов, и что @называется self в Python.
UPDATE: теперь это вики сообщества, поэтому мы можем добавить здесь большие различия.
Ruby имеет ссылку класса в классе класса
В Ruby у вас есть ссылка на класс (self) уже в классе. В Python у вас нет ссылки на класс до завершения построения класса.
Пример:
class Kaka
puts self
end
self в этом случае является классом, и этот код будет печатать "Кака". Невозможно распечатать имя класса или другими способами получить доступ к классу из тела определения класса в Python (определения внешних методов).
Все классы изменяются в Ruby
Это позволяет вам разрабатывать расширения для основных классов. Вот пример расширения рельсов:
class String
def starts_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 имеет первые классы regexps, $-variables, цикл awk/perl line by line и другие функции, которые делают его более подходящим для написания небольших сценариев оболочки, которые обрабатывают текстовые файлы или действуют как код клейма для других программ.
Ruby имеет продолжения первого класса
Благодаря выражению callcc. В Python вы можете создавать продолжения с помощью различных методов, но поддержка языка не поддерживается.
У Ruby есть блоки
С помощью инструкции "do" вы можете создать многострочную анонимную функцию в Ruby, которая будет передана в качестве аргумента в метод перед do и вызывается оттуда. В Python вы должны сделать это либо путем передачи метода, либо с помощью генераторов.
Ruby:
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 будет создавать генератор.
Ruby:
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 и расположен выше метода, а не внутри него. Они могут быть извлечены во время выполнения из файлов с помощью 1.9 Метод # source_location example use
Python имеет множественное наследование
Ruby не делает ( "специально" - см. сайт Ruby, см. здесь, как это делается в Ruby). Он повторно использует концепцию модуля как тип абстрактных классов.
У Python есть списки/dict-решения
Python:
res = [x*x for x in range(1, 10)]
Ruby:
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]
Ruby:
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'}
Ruby:
>> 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