В Ruby есть блоки; Python этого не делает.
У Python есть функции; Руби нет. В Python вы можете взять любую функцию или метод и передать их другой функции. В Ruby все является методом, и методы нельзя передавать напрямую. Вместо этого вы должны обернуть их в Proc, чтобы передать их.
И Ruby, и Python поддерживают замыкания, но по-разному. В Python вы можете определить функцию внутри другой функции. Внутренняя функция имеет доступ для чтения к переменным из внешней функции, но не для записи. В Ruby вы определяете замыкания с помощью блоков. Замыкания имеют полный доступ для чтения и записи к переменным из внешней области видимости.
В Python есть довольно выразительные списки. Например, если у вас есть список чисел, вы можете написать
[x*x for x in values if x > 15]
чтобы получить новый список квадратов всех значений больше 15. В Ruby вам нужно будет написать следующее:
values.select {|v| v > 15}.map {|v| v * v}
Код Ruby не кажется таким компактным. Это также не так эффективно, поскольку сначала он преобразует массив значений в более короткий промежуточный массив, содержащий значения больше 15. Затем он берет промежуточный массив и генерирует окончательный массив, содержащий квадраты промежуточных звеньев. Затем выкидывают промежуточный массив. Итак, во время вычислений в памяти Ruby остается 3 массива; Python нужен только список ввода и результирующий список.
Python также предоставляет аналогичные представления о картах.
Python поддерживает кортежи; Руби нет. В Ruby вы должны использовать массивы для имитации кортежей.
Ruby поддерживает операторы switch / case; Python этого не делает.
Ruby поддерживает стандартный expr ? val1 : val2
тернарный оператор; Python этого не делает.
Ruby поддерживает только одиночное наследование. Если вам нужно имитировать множественное наследование, вы можете определять модули и использовать микшеры для втягивания методов модуля в классы. Python поддерживает множественное наследование, а не смешивание модулей.
Python поддерживает только однострочные лямбда-функции. Блоки Ruby, которые являются своего рода лямбда-функциями, могут быть сколь угодно большими. Из-за этого код Ruby обычно написан в более функциональном стиле, чем код Python. Например, чтобы перебрать список в Ruby, вы обычно делаете
collection.each do |value|
...
end
Блок работает очень похоже на передаваемую функцию collection.each
. Если бы вы сделали то же самое в Python, вам бы пришлось определить именованную внутреннюю функцию, а затем передать ее в коллекцию каждого метода (если список поддерживает этот метод):
def some_operation(value):
...
collection.each(some_operation)
Это не очень красиво. Итак, как правило, в Python используется следующий нефункциональный подход:
for value in collection:
...
Безопасное использование ресурсов на двух языках сильно различается. Здесь проблема в том, что вы хотите выделить некоторый ресурс (открыть файл, получить курсор базы данных и т. Д.), Выполнить над ним произвольную операцию, а затем закрыть его безопасным образом, даже если возникнет исключение.
В Ruby, поскольку блоки настолько просты в использовании (см. №9), вы обычно кодируете этот шаблон как метод, который принимает блок для произвольной операции, выполняемой над ресурсом.
В Python передача функции для произвольного действия немного сложнее, поскольку вам нужно написать именованную внутреннюю функцию (см. №9). Вместо этого Python использует with
инструкцию для безопасной обработки ресурсов. См. Как правильно очистить объект Python? Больше подробностей.