Сравнение различий между идеями программирования Python и Ruby с помощью циклов for

Python
Сравнение различий между идеями программирования Python и Ruby с помощью циклов for

Большую часть различий между Ruby и Python можно увидеть в цикле for.

В Python есть оператор for. Объект сообщает, как взаимодействовать, а тело цикла for обрабатывает то, что возвращает объект.

Руби наоборот. В Ruby для себя (через каждого) есть метод объекта. Вызывающий объект передает тело цикла for этому методу.

В идиоме языка Python объектная модель подвержена циклам for. В Ruby циклы for подчиняются объектной модели.

То есть в Python, если вы хотите настроить процесс итерации, вы можете позволить объекту сообщить интерпретатору, как выполнять итерацию:

class Stuff:
    def __init__(self):
        self.a_list = [1,2,3,4]
        self.position = 0
    def __next__(self):
        try:
            value = self.a_list[self.position]
            self.position += 1
            return value
        except IndexError:
            self.position = 0
            raise StopIteration
    def __iter__(self):
        return self

Здесь Stuff используетnextиiterМагический метод делает себя итерируемым (становится итерируемым объектом).

for data in Stuff():
    print(data)

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

Затем в каждом методе используйте yield для взаимодействия с блоком кода, передавая значение в блок кода, чтобы сделать то, что вам нужно (блок кода является неявным параметром для любого метода).

Если мы перепишем приведенный выше код, он будет выглядеть так:

class Stuff
  def initialize
    @a_list = [1, 2, 3, 4]
  end

  def each
    for item in @a_list
      yield item
    end
  end
end

Используйте каждый для повторения:

Stuff.new().each do |item|
  puts item
end

Вместо передачи данных в цикл for (Python) передайте код цикла в данные (Ruby).

Но разница гораздо больше:

Python создает for-like конструкции для всех видов обработки, Ruby помещает обработку данных в методы.

Хороший код Python реализует отображение и фильтрацию с использованием списков и словарей, которые по своей сути имеют ту же семантику, что и for/iteration.

In [2]: [item for item in Stuff()]
Out[2]: [1, 2, 3, 4]

In [3]: [item for item in Stuff() if item % 2 == 0]
Out[3]: [2, 4]

Ruby продолжает использовать метод «сначала метод», и в дополнение к каждому методу существует ряд новых методов, обычно используемых для работы с коллекциями, а именно:

class Stuff
  ...

  def select
    out = []
    each do |e|
      # If block returns truthy on e, append to out
      if yield(e)
        out << e
      end
    end
    out
  end

  def map
    out = []
    # One line block syntax, append output of block processed on e to out
    each {|e| out << yield(e) } 
    out
end

puts Stuff.new().map {|item| item}
puts Stuff.new().select{|item| item.even?}

Python говорит: «Вы говорите нам, как перебирать ваши экземпляры, а мы решим, что делать с вашими данными». правильный код тела цикла for (или выражения).

Ruby меняет сценарий, предоставляя объектам более глубокий уровень настраиваемости. Да, в некоторых случаях мы можем добавить больше потока управления внутри блока кода. Да, мы также можем использовать метод each в качестве карты. Но Ruby позволяет объектам реализовывать карту и каждый по-разному (использование реализации «каждого» вместо «карты» может быть очень неоптимальным или даже небезопасным). Объекты Ruby имеют лучший способ обработки своих данных.

В Ruby объекты управляют функциональной видимостью. В Python это синтаксис, который управляет.

Аутентичный Python имеет твердый взгляд на обработку данных. Python говорит: «Послушай, 90% твоего кода прекрасно соответствует этим идеям, просто следуй ему и делай свою работу».

Тем не менее, Ruby говорит: «В некоторых важных случаях мы не хотим давать вызывающему объекту слишком много полномочий». Ruby не так силен в обработке данных.

Python — это скорее расширение «объектно-ориентированного» программирования на языке C. В объектно-ориентированном программном обеспечении на основе C, подобно файловым дескрипторам posix или дескрипторам окон Win32, язык не привязывает «методы» к самим объектам. Вместо этого привязки объекта к методу просто основаны на соглашении.

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

Класс метод получения «самости» в качестве своего первого аргумента, обрабатывается почти так же, как в функции Win32 или POSIX API, принимает C. Когда функция передается, они почти в зависимости от Contace Contacter.

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

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

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

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

Неудивительно, что Ruby отлично подходит для разработчиков, создающих более плавные и, возможно, более безопасные API и DSL. Ruby предполагает, что программист будет моделировать предметную область, а не среду программирования, что кажется правильным подходом для многих задач.