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


263

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

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

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

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

У Ruby есть ссылка на класс в теле класса

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

Пример:

class Kaka
  puts self
end

self в этом случае является классом, и этот код будет выводить «Kaka». Невозможно распечатать имя класса или каким-либо другим способом получить доступ к классу из тела определения класса в 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 есть регулярные выражения первого класса, переменные $, переменные циклические строки ввода awk / perl и другие функции, которые делают его более подходящим для написания небольших сценариев оболочки, которые разбирают текстовые файлы или действуют как связующий код для других программ.

Руби имеет продолжение первого класса

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

Рубин имеет блоки

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

Рубин:

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 создаст генератор.

Рубин:

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 Fibres являются и могут использоваться как генераторы, а класс 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 имеет строки документации

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

def frobnicate(bar):
    """frobnicate takes a bar and frobnicates it

       >>> bar = Bar()
       >>> bar.is_frobnicated()
       False
       >>> frobnicate(bar)
       >>> bar.is_frobnicated()
       True
    """

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

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

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

У Python есть списки / дикты

Python:

res = [x*x for x in range(1, 10)]

Рубин:

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]

Рубин:

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'}

Рубин:

>> 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


2
Что касается множественного наследования, говорить «Руби нет» неискренне. Я не могу придумать ничего, что вы можете сделать в Python с множественным наследованием, что вы не можете сделать в ruby ​​с модулями / «mixin-наследованием». (Можно даже утверждать, что включение просто модулей - это множественное наследование.)
Логан Капальдо

2
То, что вы можете сделать то же самое другим способом, является аргументом, который не имеет места. Вы можете сделать все здесь другим способом. А поскольку модули не являются классами, это не множественное наследование. Вы можете представить примеры кода того, как это делается в множественном наследовании Pythons по сравнению с модулями Rubys.
Леннарт Регебро

3
Модули не являются классами, но классы являются модулями. % ruby ​​-e 'p Class <Module' true
Логан Капальдо

8
-1 К сожалению, этот вопрос не достигает своей цели, и большинство предполагаемых различий вообще не являются различиями, и дезинформация изобилует!
предвзятость

2
Модуль включает в себя множественное наследование, не только в концепции, но и в реальной реализации в интерпретаторе Ruby. Когда модуль Ruby включен, он внедряется в цепочку наследования точно так же, как и суперклассы. Метод разрешения такой же. В Ruby несколько модулей включают в себя множественное наследование. Любой, кто хочет оспорить это как семантически "не то же самое", что и множественное наследование, просто педантичен. Какой смысл в том, чтобы что-то не было «одним и тем же», если эффект идентичен и так же легко достигается? Различие без разницы.
Дэйв Симс

Ответы:


34

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

Например, простое определение eachметода Arrayможет выглядеть примерно так:

class Array
  def each
    for i in self  
      yield(i)     # If a block has been passed, control will be passed here.
    end  
  end  
end  

Тогда вы можете вызвать это так:

# Add five to each element.
[1, 2, 3, 4].each{ |e| puts e + 5 }
> [6, 7, 8, 9]

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


6
@ Леннарт: кроме твоего примера просто быть ужасным, это также синтаксически неправильно.

2
@unbeknow: A, верно. Но если бы это была функция вместо печати, это бы сработало. В python 3 это работает: [print (e + 5) для e в [1,2,3,4]] И когда дело доходит до ужаса, я думаю, что код рубина выше ужасен, так что это явно субъективно и поэтому не часть этого вопроса. @ Джон Я не говорю, что это эквивалентно, я говорю, что не очевидно, в чем отличие от вашего примера. @ Бастиен, нет, но то, что вы можете делать подобные вещи, не означает, что они одинаковы. Различия здесь должны быть перечислены, даже если есть другие способы сделать это.
Леннарт Регебро

22
Я программист на Python. Я хотел бы увидеть пример того, как блоки Ruby помогают вам писать что-то более лаконичное или красивое, чем в Python, потому что в нем нет блоков. Ваш пример может быть написан: для i в [1, 2, 3, 4]: print (i + 5). Он не использует блоки, но он лаконичен и красив, а также рубин в каждом примере.
Мануэль Церон

10
@Manuel, procs полезны для присоединения функторов к нетривиальным структурам данных (деревьям, графам ...), которые не могут быть зациклены и, следовательно, требуют специальных итераторов для прохождения. Блоки, которые являются анонимными процессами, позволяют вам реализовать функтор в одном выражении (вместо определения, а затем реализовать), что значительно ускоряет процесс кодирования и проясняет намерение. Например, если бы вы создавали структуру данных графа, вы могли бы определить один «каждый» итератор, а затем смешать Enumerable, который мгновенно предоставил бы вам доступ к десяткам итераторов (sort, all ?, any ?, grep). Теперь вы называете блок ...
смещение

4
@RommeDeSerieux, потому что ему нужно имя на языке! Более того, это функциональный объект, а не функция. Давайте посмотрим на документы Ruby: «Объекты Proc - это блоки кода, которые были связаны с набором локальных переменных», поэтому анонимный Proc - это просто блок, и, конечно же, это не просто функция!
предвзятость

28

Пример Python

Функции являются первоклассными переменными в Python. Вы можете объявить функцию, передать ее как объект и перезаписать:

def func(): print "hello"
def another_func(f): f()
another_func(func)

def func2(): print "goodbye"
func = func2

Это фундаментальная особенность современных скриптовых языков. JavaScript и Lua тоже это делают. Руби не относится к функциям таким образом; именование функции вызывает ее.

Конечно, в Ruby есть способы сделать это, но это не первоклассные операции. Например, вы можете обернуть функцию с помощью Proc.new, чтобы рассматривать ее как переменную - но тогда она больше не является функцией; это объект с методом "вызова".

Функции Руби не первоклассные объекты

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

def func; p "Hello" end
def another_func(f); method(f)[] end
another_func(:func)      # => "Hello"

def func2; print "Goodbye!"
self.class.send(:define_method, :func, method(:func2))
func                     # => "Goodbye!"

method(:func).owner      # => Object
func                     # => "Goodbye!"
self.func                # => "Goodbye!"    

8
Вы сильно запутались. Первоклассные объекты присваиваются по присваиванию:, а x = yне по вызову self.class.send(:define_method, :func, method(:func2)). Ваш «контрпример» показывает, что функции Ruby не являются первоклассными. Если вы не согласны, не стесняйтесь опубликовать свой собственный ответ; не суй свое замешательство в мое.
Гленн Мейнард

7
Вещи, определенные def ... endв ruby, не являются функциями. Это методы (как вы их определили Kernel). Методы могут быть связаны (используя #methodметод), которые затем являются объектами. Самое близкое, что ruby ​​имеет к функциям, - это Procэкземпляры, которые также являются объектами и могут передаваться или вызываться. Он также имеет специальный синтаксис для передачи одного обратного вызова Procметоду, как обсуждает Джон Феминелла в своем ответе .
рапион

4
@Glenn: я понимаю, что вы говорите, но я бы поспорил с утверждением, что переопределение функций Руби - методы - это отдельная семантическая концепция. Если вы хотите поиграть в игру с определением, наиболее обязательный код - это процедуры, а не функции. Я не пытаюсь быть сложным, просто я считаю, что определения и точность важны. Я согласен, что манипулирование UnboundMethodможет быть PITA, хотя.
Рапион

5
@ Гленн: Красота в глазах смотрящего. Тем не менее, методы являются первоклассными объектами, выполняя определение (в данном случае я имею в виду определение из Википедии). Может быть, у вас есть другое определение первого класса? Нужна ли им карта Platinum Frequent Flier, чтобы попасть в первый класс?
смещение

4
@Glenn Ознакомьтесь с разделом часто задаваемых вопросов SO "Другие люди могут редактировать мои материалы ?!" - это сообщество Wiki.
предвзятость

26

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

Мне нравится синтаксис Python. Однако вам придется копать немного глубже синтаксиса, чтобы найти истинную красоту Ruby. В последовательности Руби есть дзен-подобная красота. Хотя ни один тривиальный пример не может объяснить это полностью, я попытаюсь придумать один здесь, чтобы объяснить, что я имею в виду.

Поменяйте местами слова в этой строке:

sentence = "backwards is sentence This"

Когда вы думаете о том, как вы это сделаете, вы сделаете следующее:

  1. Разделите предложение на слова
  2. Поменять слова
  3. Повторно соедините слова обратно в строку

В Ruby вы бы сделали это:

sentence.split.reverse.join ' '

Точно так же, как вы думаете об этом, в той же последовательности, один вызов метода за другим.

В Python это будет выглядеть примерно так:

" ".join(reversed(sentence.split()))

Это не сложно понять, но у него не совсем тот же поток. Предмет (предложение) похоронен в середине. Операции представляют собой сочетание функций и методов объекта. Это тривиальный пример, но при работе с Ruby и его понимании можно найти много разных примеров, особенно в отношении нетривиальных задач.


1
Я согласен. Кажется, что Ruby течет естественно, когда я пишу это, так что «zenlike» - это хороший термин.
Оловянный Человек

18

У Python менталитет «мы все здесь взрослые». Таким образом, вы обнаружите, что в Ruby есть такие вещи, как константы, в то время как в Python нет (хотя константы Ruby только вызывают предупреждение). С точки зрения Python, если вы хотите сделать что-то постоянным, вы должны поместить имена переменных во все заглавные буквы, а не изменять их.

Например, Ruby:

>> PI = 3.14
=> 3.14
>> PI += 1
(irb):2: warning: already initialized constant PI
=> 4.14

Python:

>>> PI = 3.14
>>> PI += 1
>>> PI
4.1400000000000006

19
Ха ... это просто напоминает мне, что, по крайней мере, в python 2. * вы могли делать "True, False = False, True" ... Я считаю, что они правильно исправили это в Python 3.0 ... это то, что вы должны быть лишенным возможности делать.
Том

11
Лично мне нравятся строгие правила, применяемые языком, потому что он делает весь код, написанный на этом языке, согласованным. Это заставляет вас следовать рекомендациям, и разработчики, читающие ваш код, могут сразу увидеть, что к чему. Хотя большинство Python-кодеров используют один и тот же общий «стиль», я видел довольно большие несоответствия, которые были бы невозможны в Ruby.
Саша Чедыгов

8
@ bias - я не уверен, почему ты меня опровергаешь. Этот ответ не согласен или не согласен с тем, как Python работает. Это просто констатация факта.
Джейсон Бейкер

13
@ Джейсон "мы все здесь взрослые" - это факт? Я хотел бы назвать это мнение обернутым вокруг функции, отсюда и голосование против.
смещение

7
@ bias - Сказать «мы все взрослые здесь» не было легким. Это неофициальный девиз Python, который, мне кажется, лучше всего объяснить здесь: mail.python.org/pipermail/tutor/2003-October/025932.html
Эван Портер

18

Вы можете импортировать только определенные функции из модуля в Python. В Ruby вы импортируете весь список методов. Вы можете «импортировать» их в Ruby, но дело не в этом.

РЕДАКТИРОВАТЬ:

давайте возьмем этот модуль Ruby:


module Whatever
  def method1
  end

  def method2
  end
end

если вы включите его в свой код:


include Whatever

вы увидите , что оба method1 и method2 были добавлены в пространство имен. Вы не можете импортировать только method1 . Вы либо импортируете их оба, либо не импортируете их вообще. В Python вы можете импортировать только методы по вашему выбору. Если бы у этого было имя, может быть, это было бы названо выборочным импортом?


2
О верно! Python любит пространства имен. Разве это не так в Ruby? Вы не import bla; bla.foo()в Руби?
Леннарт Регебро

2
Вы можете импортировать только функцию a, а не все функции внутри. Например, если вы включаете модуль Ruby, который объявляет 3 нестатические функции, вы получаете их все в своем пространстве имен. В Python вы должны написать из модуля import *.
Geo

6
Разве это не приводит к большому беспорядку пространства имен?
Леннарт Регебро

1
Я думаю, что это так. Вот что я ненавижу в модулях Ruby.
Geo

8
В Ruby на самом деле нет модульной системы в том же смысле, что и в python. Требуется работает в основном как текстовое включение с некоторыми проверками на наличие дублирующих включений. Вы можете (ab) использовать модули в качестве пространств имен, но moduleна самом деле это немного неправильно. Модули в основном классы без new, allocateметоды. Они лучше всего работают как способ совместного использования кода для каждого класса / объекта, а не как механизм для разделения библиотек или для обмена кодом между программами.
Логан Капальдо

16

С сайта Руби :

Сходства, как с Python, в Ruby, ...

  • Там есть интерактивная подсказка (называется irb).
  • Вы можете читать документы в командной строке (с помощью команды ri вместо pydoc).
  • Особых ограничителей строки нет (кроме обычного перевода строки).
  • Строковые литералы могут занимать несколько строк, например строки Python с тройными кавычками.
  • Скобки - для списков, а скобки - для диктовок (которые в Ruby называются «хешами»).
  • Массивы работают одинаково (при их добавлении получается один длинный массив, но составляется таким образом a3 = [ a1, a2 ] получается массив массивов).
  • Объекты строго и динамически типизированы.
  • Все является объектом, а переменные - это просто ссылки на объекты.
  • Хотя ключевые слова немного отличаются, исключения работают примерно одинаково.
  • У вас есть встроенные инструменты документооборота (Ruby's называется rdoc).

Отличия В отличие от Python, в Ruby, ...

  • Строки изменчивы.
  • Вы можете создавать константы (переменные, значение которых вы не собираетесь менять).
  • Существуют некоторые принудительные условные обозначения (например, имена классов начинаются с заглавной буквы, переменные начинаются со строчной буквы).
  • Существует только один вид списка контейнеров (массив), и он может изменяться.
  • Строки в двойных кавычках допускают escape-последовательности (например, \ t) и специальный синтаксис «подстановка выражений» (который позволяет вставлять результаты выражений Ruby непосредственно в другие строки без необходимости «добавлять» + «строки» + «вместе») , Строки в одинарных кавычках похожи на «необработанные строки» Python.
  • Нет классов «новый стиль» и «старый стиль». Всего один вид.
  • У вас никогда нет прямого доступа к атрибутам. С Ruby это все вызовы методов.
  • Скобки для вызовов методов обычно необязательны.
  • Есть общедоступный, закрытый и защищенный для обеспечения доступа, а не Python _voluntary_ underscore __convention__.
  • «Mixin's» используются вместо множественного наследования.
  • Вы можете добавлять или изменять методы встроенных классов. Оба языка позволяют открывать и изменять классы в любой момент, но Python запрещает модификацию встроенных модулей, а Ruby - нет.
  • У вас есть истина и ложь вместо Истина и Ложь (и ноль вместо Нет).
  • Когда проверяется на правду, только ложь и ноль оценивают как ложное значение. Все остальное верно (включая 0, 0.0, "" и []).
  • Это elsif вместо elif.
  • Требуется вместо импорта. В противном случае, использование то же самое.
  • Комментарии в обычном стиле в строке (строках) над вещами (вместо строк документации под ними) используются для создания документов.
  • Есть несколько ярлыков, которые, хотя и дают вам больше запоминания, вы быстро учитесь. Они делают Ruby увлекательным и очень продуктивным.

2
«Требуется вместо импорта. Иначе, использование то же самое». Кажется, совершенно неточно.
Гленжамин

В Ruby также есть наборы, которые люди редко используют, но они встроены. Так что я могу сказать, stuff_in_backpack = Set.new; stuff_in_backpack << "компьютер"; stuff_in_backpack << "обувь"; # и набор будет содержать все значения без гарантии порядка.
zachaysan

12

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

В основном они делятся с Perl. Первоклассные встроенные регулярные выражения, $ -Variables, полезные параметры командной строки, такие как Perl (-a, -e) и т. Д.

Вместе с кратким, но выразительным синтаксисом он идеально подходит для такого рода задач.

Python для меня - это скорее динамически типизированный бизнес-язык, который очень прост в изучении и имеет аккуратный синтаксис. Не такой "крутой", как Ruby, но аккуратный. Что Python имеет для Ruby для меня, так это огромное количество привязок для других библиотек. Привязки к Qt и другим библиотекам GUI, многие библиотеки поддержки игр и и и. Рубин имеет гораздо меньше. Хотя часто используемые привязки, например, к базам данных, имеют хорошее качество, я обнаружил, что нишевые библиотеки лучше поддерживаются в Python, даже если для той же библиотеки есть также привязка Ruby.

Итак, я бы сказал, что оба языка имеют свое использование, и именно эта задача определяет, какой из них использовать. Оба достаточно просты в освоении. Я использую их бок о бок. Ruby для скриптинга и Python для автономных приложений.


1
Вопрос от кого-то, кто еще не знает Ruby: что вы подразумеваете под "$ -Variables"? Вы имеете в виду глобальные переменные? Если это так, в Python переменная, определенная в модуле вне класса или функции, является глобальной. Если нет - в чем разница?
Anon

1
Anon: если вы объявите переменную $ где-либо в коде, она будет глобальной из-за префикса. Таким образом, не имеет значения, где он определен, он всегда глобален и всегда известен как таковой.
Роберт К

8
Не совсем, на самом деле я имел в виду предопределенные переменные, такие как $ _, $ 1 и т. Д. Они автоматически заполняются значениями самим ruby. $ _ - последняя прочитанная строка. $ 1, $ 2 и т. Д. - совпадения регулярного выражения из последнего совпадения. Смотрите здесь полный список: zenspider.com/Languages/Ruby/QuickRef.html#17 Это в основном хак для компактных скриптов. Вы также можете получить всю информацию через вызовы API, но используя переменные $, это более кратко. Такого рода переменные просто не соответствуют стилю Python, они намеренно не учитывают их.
Хаффакс

Спасибо за эту ссылку zenspider - искал что-то подобное для быстрого (не учебного) ощущения для Ruby.
Anon

12

Я не думаю, что «у Ruby есть X, а у Python нет, а у Python есть Y, а у Ruby нет» - самый полезный способ взглянуть на это. Это довольно похожие языки со многими общими возможностями.

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


5
Я согласен, что лямбды имеют ограниченную область применения и во многих случаях бесполезны. Однако я не думаю, что будет справедливо сказать, что программисты на Python избегают их как чумы.
Джейсон Бейкер

1
Я согласен, что лямбды часто используются с Python - как с картой, фильтром, сокращением. Большая разница в том, что лямбды Python ограничены выражениями, тогда как блоки Ruby могут быть многострочными и содержать операторы. Мое общее впечатление от того, что я читал о Ruby, заключается в том, что эта особенность, в частности, заставляет Rubyists использовать DSL-подход, тогда как Pythonistas более склонны к созданию API. Моя информация о Ruby все еще очень поверхностна.
Anon

2
@Lennart: Многострочные блоки все время используются в Ruby - чаще, чем я вижу лямбды, используемые в идиоматическом коде Python. Типичный пример см. На info.michael-simons.eu/2007/08/06/rails-respond_to-method .
Чак

1
@ Леннарт: Нет, он не использует доходность. (Выход Ruby полностью отличается от выходов Python - он не возвращает генератор.) Не было бы смысла писать for format in respond_to(). respond_toМетод ничего значимого не возвращается - он просто реагирует на текущий запрос HTTP. doВ respond_to doначале блока. В этом блоке мы говорим с временным объектом (помеченным formatв этом примере), который реализует очень простой DSL для ответа на HTTP-запрос.
Чак

3
Можете ли вы «смешать Enumerable» с генератором и получить 30 новых замечательных итераторов? Вам нужно взглянуть на язык в целом, прежде чем вы поймете, почему блоки / Procs хороши.
смещение

12

Я хотел бы предложить вариант исходного вопроса: «Что у Ruby есть, чего нет у Python, и наоборот?» который допускает неутешительный ответ: «Ну, что вы можете сделать с Ruby или Python, чего нельзя сделать в Intercal?» Ничего на этом уровне, потому что Питон и Руби являются частью огромной королевской семьи, сидящей на троне приближенного Тьюринга.

Но как насчет этого:

Что можно сделать изящно и хорошо в Python, что нельзя сделать в Ruby с такой красотой и хорошей инженерией, или наоборот?

Это может быть гораздо интереснее, чем просто сравнение характеристик.


комментарий в лучшем случае. все еще мой +1
nawfal

11

Python имеет явный встроенный синтаксис для списочных представлений и генераторов, тогда как в Ruby вы бы использовали блоки map и code.

сравнить

list = [ x*x for x in range(1, 10) ]

в

res = (1..10).map{ |x| x*x }

как списочные представления не являются простым Python ? и есть функция карты в Python.
SilentGhost

Но в Ruby нет синтаксиса понимания списков
Дарио

Python: res = map (лямбда x: x * x, диапазон (1,10))
GogaRieger

Питон:res=map(2 .__rpow__, range(1,10))
Джон Ла Рой

11

«Переменные, начинающиеся с заглавной буквы, становятся константами и не могут быть изменены»

Неправильно. Они могут.

Вы только получите предупреждение, если вы делаете.


2
Если какой-либо язык предупреждает вас об операции, я считаю, что вы вполне можете считать эту операцию "невозможной". Все остальное безумие.
porgarmingduod

11

Несколько больше об инфраструктуре:

  • Python имеет гораздо лучшую интеграцию с C ++ (через такие вещи, как Boost.Python , SIP и Py ++ ), чем Ruby, где параметры кажутся либо написанными непосредственно в API интерпретатора Ruby (что вы также можете делать с Python, конечно, но в обоих случаях это низкоуровневое, утомительное и подверженное ошибкам) ​​или использование SWIG (что, хотя оно работает и, безусловно, прекрасно, если вы хотите поддерживать много языков, не так хорошо, как Boost.Python или SIP, если Вы специально хотите связать C ++).

  • В Python есть несколько сред веб-приложений (Django, Pylons / Turbogears, web.py, вероятно, по крайней мере полдюжины других), тогда как в Ruby (эффективно) есть одна: Rails. (Другие веб-фреймворки на Ruby существуют, но, похоже, им сложно добиться успеха в Rails). Этот аспект хорош или плох? Трудно сказать, и, вероятно, довольно субъективно; Я легко могу представить аргументы, что ситуация с Python лучше, а ситуация с Ruby лучше.

  • В культурном отношении сообщества Python и Ruby кажутся несколько различными, но я могу только намекать на это, поскольку у меня нет такого большого опыта взаимодействия с сообществом Ruby. Я добавляю это главным образом в надежде, что кто-то, у кого есть большой опыт с обоими, может усилить (или отклонить) это утверждение.


7
Ваш второй пункт в лучшем случае дезинформирован. Вы должны начать с рассмотрения Стойки и Синатры
Макс Огден

6
Я четко отмечаю, что существуют другие стеки Rails; Я просто не думаю, что кто-то на самом деле их использует. Проверка Синатры и Стойки точно не изменила это впечатление. Вы действительно думаете, что, скажем, у Sinatra (всего 94 SO) или Camping (всего 2 SO) или у кого-то еще есть реальная база пользователей / сообщество? Насколько я могу судить, большинство из них даже не имеют реальных пользователей. Сравните с Django (4K +) или Rails (7K +), или даже web.py в этом отношении.
Джек Ллойд,

1
Sinatra на самом деле довольно популярен для различных легких задач из-за своей DSL. Его просто меньше используют, потому что RailC от Rail предоставляет больше. Rails фактически построен на Rack - это то, что делает возможным Phusion Passenger.
альтернатива

11

Бесстыдно скопировал / вставил из: Ответ Алекса Мартелли о теме « Что лучше в Ruby, чем Python » из списка рассылки comp.lang.python .

18 августа 2003, 10:50 Эрик Макс Фрэнсис написал:

«Брэндон Дж. Ван Эвери» писал:

Что лучше в Ruby, чем в Python? Я уверен, что что-то есть. Что это?

Разве не было бы намного больше смысла спрашивать об этом у людей с Ruby, а не у людей с Python?

Может или не может, в зависимости от своих целей - например, если в чьи-то цели входит «социологическое исследование» сообщества Python, то постановка вопросов этому сообществу, скорее всего, покажет больше информации о нем, чем размещение в другом месте. :-).

Лично я с радостью воспользовался возможностью, чтобы последовать однодневному уроку Дэйва Томаса по Ruby на прошлой OSCON. Под тонким слоем различий в синтаксисе я нахожу Ruby и Python удивительно похожими - если бы я вычислял минимальное связующее дерево практически для любого набора языков, я почти уверен, что Python и Ruby будут первыми двумя листами, которые объединятся в промежуточный узел :-).

Конечно, в Ruby мне надоело набирать глупый «конец» в конце каждого блока (а не просто делать отступы) - но потом я стараюсь не вводить одинаково глупый «:», который требует Python при начало каждого блока, так что почти мыть :-). Другие различия в синтаксисе, такие как «@foo» и «self.foo» или более высокая значимость регистра в Ruby vs Python, для меня практически не имеют значения.

Другие, без сомнения, основывают свой выбор языков программирования именно на таких проблемах, и они вызывают самые горячие споры - но для меня это всего лишь пример одного из законов Паркинсона в действии (количество споров по проблеме обратно пропорционально актуальное значение).

редактировать (до 6/19/2010 11:45): это также известно как «покраска велосипеда» (или, если коротко, «велосипедная прогулка») - опять же это ссылка на Норткот Паркинсон, который дал «дебаты» на какой цвет рисовать велосипед "как типичный пример" горячих дебатов на тривиальные темы ". (конец из-Edit).

Одно из синтаксических различий, которое я считаю важным, и в пользу Python - но другие люди, несомненно, будут думать об обратном, - это «как вызвать функцию, которая не принимает параметров». В Python (как в C) для вызова функции вы всегда применяете «оператор вызова» - завершающие скобки сразу после вызываемого объекта (внутри этих завершающих скобок идут аргументы, которые вы передаете в вызове - если вы не передаете аргументы, тогда круглые скобки пусты). Это оставляет простое упоминание о любогообъект, без участия оператора, как означающий просто ссылку на объект - в любом контексте, без особых случаев, исключений, специальных правил и тому подобного. В Ruby (как в Pascal) для вызова функции WITH с аргументами вы передаете аргументы (обычно в круглых скобках, хотя это не всегда так) - НО, если функция не принимает аргументов, тогда просто упоминание функции неявно вызывает ее. Это может оправдать ожидания многих людей (по крайней мере, без сомнения, тех, чей единственный предыдущий опыт программирования был с Pascal или другими языками с похожим «неявным вызовом», таким как Visual Basic) - но для меня это означает простое упоминание объекта может означать ЛИБО ссылку на объект, ИЛИ вызов объекта, в зависимости от типа объекта - и в тех случаях, когда я могу Чтобы получить ссылку на объект, просто упомянув его, мне нужно будет использовать явное «дайте мне ссылку на это, НЕ называйте это!» операторы, которые не нужны в противном случае. Я чувствую, что это влияет на «первоклассность» функций (или методов, или других вызываемых объектов) и возможность плавного обмена объектами. Поэтому для меня это специфическое различие в синтаксисе является серьезной черной чертой против Ruby, но я понимаю, почему другие поступили бы иначе, хотя я едва ли мог с ними не согласиться более решительно :-). функций (или методов, или других вызываемых объектов) и возможность плавного обмена объектами. Поэтому для меня это специфическое различие в синтаксисе является серьезной черной чертой против Ruby, но я понимаю, почему другие поступили бы иначе, хотя я едва ли мог с ними не согласиться более решительно :-). функций (или методов, или других вызываемых объектов) и возможность плавного обмена объектами. Поэтому для меня это специфическое различие в синтаксисе является серьезной черной чертой против Ruby, но я понимаю, почему другие поступили бы иначе, хотя я едва ли мог с ними не согласиться более решительно :-).

Ниже синтаксиса мы сталкиваемся с некоторыми важными различиями в элементарной семантике - например, строки в Ruby являются изменяемыми объектами (как в C ++), в то время как в Python они не являются изменяемыми (как в Java или, я полагаю, в C #). Опять же, люди, которые судят в первую очередь по тому, с чем они уже знакомы, могут подумать, что это плюс для Ruby (если, конечно, они не знакомы с Java или C # :-). Я, я думаю, что неизменяемые строки - отличная идея (и я не удивлен, что Java, независимо от того, я думаю, заново изобрел эту идею, которая уже была в Python), хотя я также не возражаю против использования типа «изменяемый строковый буфер» (и, в идеале, более простой в использовании, чем собственные строковые буферы Java); и я не даю это суждение из-за знакомства - до изучения Java, все данные являются неизменяемыми, все языки, которые я знал, имели изменяемые строки - но когда я впервые увидел идею неизменяемой строки в Java (которую я выучил задолго до изучения Python), она сразу показалась мне превосходной, очень хорошо подходящей для эталонная семантика языка программирования более высокого уровня (в отличие от семантики значений, которая лучше всего подходит для языков ближе к машине и дальше от приложений, таких как C) со строками в качестве первоклассного, встроенного (и довольно решающее значение) тип данных.

У Ruby есть некоторые преимущества в элементарной семантике - например, удаление «списков против кортежей» в Python чрезвычайно тонкое различие. Но в основном счет (как я считаю, с простотой большой плюс и тонкие, умные различия заметным минусом) против Ruby (например, с закрытыми и полуоткрытыми интервалами, с обозначениями a..b и a .. .b [кто-нибудь хочет утверждать, что очевидно, что есть что? -)], глупо - ИМХО, конечно!). Опять же, люди, которые считают, что наличие в основе языка множества похожих, но слегка отличающихся друг от друга вещей - ПЛЮС, а не МИНУС, будут, конечно, считать это «наоборот» из того, как я их считаю :-).

Не надо вводить в заблуждение этими сравнениями, думая, что два языка оченьдругой, заметьте. Это не так. Но если бы меня попросили сравнить «capelli d'angelo» с «спагеттини», указав, что эти два вида макаронных изделий практически ни для кого не различимы и взаимозаменяемы в любом блюде, которое вы, возможно, захотите приготовить, я бы неизбежно перейти к микроскопическому исследованию того, как длины и диаметры незаметно различаются, как концы нитей сужаются в одном случае, а не в другом, и т. д., чтобы попытаться объяснить, почему я лично предпочел бы иметь капеллу. 'angelo как паста в любом бульоне, но предпочел бы спагеттини в качестве pastasciutta с подходящими соусами для таких длинных тонких форм пасты (оливковое масло, рубленый чеснок, рубленый красный перец и мелко нарезанные анчоусы, например - но если вы нарезали чеснок и перец вместо того, чтобы их измельчать, то вам следует выбрать более тонкое тело спагетти, а не более тонкую мимолетность спагеттини, и было бы хорошо отказаться от орехов и добавить вместо этого свежий весенний базилик [ или даже - я еретик ...! - легкая мята ...] листья - в самый последний момент перед подачей блюда). Упс, извините, это показывает, что я еду за границу и у меня не было пасты некоторое время, я думаю. Но аналогия все еще довольно хороша! -) - легкая мята ...] листья - в самый последний момент перед подачей блюда). Упс, извините, это показывает, что я еду за границу и у меня не было пасты некоторое время, я думаю. Но аналогия все еще довольно хороша! -) - легкая мята ...] листья - в самый последний момент перед подачей блюда). Упс, извините, это показывает, что я еду за границу и у меня не было пасты некоторое время, я думаю. Но аналогия все еще довольно хороша! -)

Итак, вернемся к Python и Ruby, мы подошли к двум важным аспектам (с точки зрения собственно языка - оставление библиотек и других важных вспомогательных элементов, таких как инструменты и среды, как встраивать / расширять каждый язык и т. Д. И т. Д.) это пока - они не будут применяться ко всем РЕАЛИЗАЦИЯМ каждого языка в любом случае, например, Jython против классического Python, являющегося двумя реализациями языка Python!):

  1. Итераторы и кодовые блоки Ruby против итераторов и генераторов Python;

  2. ОБЩАЯ, безудержная «динамичность» Руби, включая возможность
    «вновь открывать» любой существующий класс, включая все встроенные, и изменять его поведение во время выполнения - по сравнению с обширной, но ограниченной динамикой Python , которая никогда не меняет поведение существующих встроенные классы и их экземпляры.

Лично я считаю 1 стиркой (различия настолько глубоки, что я легко могу видеть, как люди ненавидят любой подход и меняют друг друга, но в МОИХ личных масштабах плюсы и минусы почти сглаживаются); и 2 решающий вопрос - тот, который делает Ruby гораздо более подходящим для «ковыряния», НО Python в равной степени более подходящим для использования в крупных производственных приложениях. В некотором смысле это забавно, потому что оба языка настолько НАМНОГО более динамичны, чем большинство других, что в конечном итоге ключевое отличие между ними от моего POV должно зависеть от этого - что Ruby "идет в одиннадцать" в этом отношении (ссылка вот к "Spinal Tap", конечно). В рубинеЯ могу сделать это ! Т.е. я могу динамически изменить встроенный класс строк, чтобы a = "Hello World" b = "hello world", если a == b print "равно! \ N", иначе print "иначе! \ N" end WILL print " равный». В питоне НЕТ, как я могу это сделать. В целях метапрограммирования, реализации экспериментальных сред и т. П. Эта удивительная динамическая способность Ruby чрезвычайно привлекательным. НО - если мы говорим о больших приложениях, разработанных многими людьми и поддерживаемых еще большим количеством, в том числе всевозможных библиотек из разных источников, и нуждающихся в запуске на клиентских сайтах ... ну, я НЕ ХОЧУ язык, который является довольно динамичным, большое спасибо. Я ненавижу саму идею о том, что какая-то библиотека невольно ломает другие несвязанные, которые полагаются на то, что эти строки различны - это своего рода глубоко и глубоко скрытый «канал», между кусками кода, которые СМОТРЯ разделяют, и ДОЛЖНЫ БЫТЬ отделенными, что означает смерть в масштабное программирование. Позволяя любому модулю влиять на поведение любого другого «скрытно», возможность изменять семантику встроенных типов - это просто ПЛОХАЯ идея для программирования производственных приложений,

Если бы мне пришлось использовать Ruby для такого большого приложения, я бы постарался опираться на ограничения стиля кодирования, множество тестов (которые будут перезапущены всякий раз, когда НИЧЕГО изменится - даже то, что должно быть совершенно не связано ...) и тому подобное, запретить использование этой языковой функции. Но НЕ иметь эту функцию, во-первых, еще лучше, на мой взгляд, так же, как сам Python был бы еще лучшим языком для разработки приложений, если бы определенное количество встроенных компонентов могло быть «прибито», поэтому я ЗНАЛ, что например, len ("ciao") равно 4 (вместо того, чтобы подсознательно беспокоиться о том, изменил ли кто-нибудь привязку имени 'len' в модуле builtins ...). Я очень надеюсь, что в конечном итоге Python «приметит» свои встроенные модули.

Но проблема незначительна, поскольку повторное связывание встроенных модулей является устаревшим, а также редкой практикой в ​​Python. В Ruby это кажется мне важным - так же, как слишком мощные средства макросов других языков (таких как, скажем, Dylan) представляют аналогичные риски по моему собственному мнению (я надеюсь, что Python никогда не получит такую ​​мощную систему макросов, нет Независимо от того, «позволять ли людям определять свои собственные предметно-ориентированные маленькие языки, встроенные в сам язык», - это, IMHO, подорвало бы замечательную полезность Python для разработки приложений, представив «привлекательную неприятность» потенциальному тинкеру, который таится в сердце каждого программиста ...).

Alex


9

Некоторые другие из:

http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/to-ruby-from-python/

(Если я что-то неправильно истолковал или что-то из этого изменилось на стороне Ruby с тех пор, как была обновлена ​​эта страница, кто-то может свободно редактировать ...)

Строки изменчивы в Ruby, а не в Python (где новые строки создаются «изменениями»).

В Ruby есть некоторые обязательные условные обозначения, в Python - нет.

Python имеет списки и кортежи (неизменяемые списки). В Ruby есть массивы, соответствующие спискам Python, но их неизменный вариант отсутствует.

В Python вы можете напрямую обращаться к атрибутам объекта. В Ruby это всегда с помощью методов.

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

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

Python имеет множественное наследование. У Руби есть "миксин".

И еще одна очень актуальная ссылка:

http://c2.com/cgi/wiki?PythonVsRuby

Который, в частности, ссылается на еще один хороший комментарий Алекса Мартелли , который также публикует здесь много полезных вещей на SO:

http://groups.google.com/group/comp.lang.python/msg/028422d707512283


1
В ruby ​​вы можете просто заморозить свой массив, чтобы изменить его на что-то неизменное
user163365

Отличный пост Алекса Мартелли :)
Skilldrick

8

Я не уверен в этом, поэтому сначала добавлю его в качестве ответа.

Python рассматривает несвязанные методы как функции

Это означает, что вы можете вызывать метод как theobject.themethod()или TheClass.themethod(anobject).

Изменить: Хотя разница между методами и функциями невелика в Python и не существует в Python 3, он также не существует в Ruby, просто потому что Ruby не имеет функций. Когда вы определяете функции, вы на самом деле определяете методы для объекта.

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


У Ruby вообще нет функций. Тем не менее, TheClass.instance_method(:themethod).bind(anobject).callбудет эквивалентный рубин.
Логан Капальдо

Ой. Итак, существует какой-то магический основной класс, когда вы определяете функцию, которая не принадлежит явному классу?
Леннарт Регебро

Да, методы, определенные на верхнем уровне, являются частными методами Object.
Логан Капальдо

1
FWIW, кажется, что в Python функции и методы на самом деле имеют один и тот же тип, и их различное поведение происходит от дескрипторов: users.rcn.com/python/download/… .
Бастьен Леонар

1
Но если вы привязываете его к объекту, то это не обязательно. Duh. :-) И в Python они тоже самое. Просто у Руби на самом деле нет функций. А это значит, что мое утверждение верно. Вы можете вызвать несвязанный метод, как если бы это была функция в Python. И это на самом деле полезно, это означает, например, что вы можете вызывать метод, определенный в классе, для объекта, который не имеет этого класса, что иногда полезно.
Леннарт Регебро

7

Я хотел бы упомянуть API дескриптора Python, который позволяет настраивать «связь» между объектами и атрибутами. Также следует отметить, что в Python можно свободно реализовывать альтернативный протокол, переопределяя значение по умолчанию, заданное в реализации __getattribute__метода по умолчанию . Позвольте мне дать более подробную информацию о вышеупомянутом. Дескрипторы регулярные занятия с __get__, __set__и / или __delete__методов. Когда интерпретатор встречает что-то подобное anObj.anAttr, выполняется следующее:

  • __getattribute__ метод anObj вызывается
  • __getattribute__ извлекает объект anAttr из класса dict
  • он проверяет, есть ли у объекта abAttr __get__, __set__или__delete__ вызываемые объекты
  • контекст (т. е. объект или класс вызывающего объекта и значение вместо последнего, если у нас есть установщик) передается вызываемому объекту
  • результат возвращается.

Как уже упоминалось, это поведение по умолчанию. Каждый свободен изменить протокол, повторно внедрив __getattribute__.

Эта техника намного мощнее декораторов.


6

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

Следовательно, вы можете реализовать классные вещи, такие как amb-оператор


Хотелось бы, чтобы я понял callcc. Можете ли вы дать более приземленный сценарий применения, чем «Неоднозначный оператор» МакКарти, чтобы оценить его достоинства? Я имею в виду что-то реальное, а не что-то напуганное CS?
ThomasH

"Funky CS вещи" это реально. Потратьте некоторое время на изучение: intertwingly.net/blog/2005/04/13/Continuations-for-Curmudgeons
Стивен Эйлерт,


5

В Python есть строки документации, а в ruby ​​нет ... Или, если это не так, они не доступны так же легко, как в python.

Ps. Если я ошибаюсь, пожалуйста, оставьте пример? У меня есть обходной путь, который я мог бы легко запрограммировать на уроки, но я бы хотел, чтобы документация была как бы «родным способом».


3
не имеет строки документации, но есть RDoc. Так что да, не так легко доступны, но не скрыты на 100%.
Омар Куреши

Ruby не использует строки документации. Это делает документацию по-другому.
Чак

1
Омар: да, я знаю о rdoc, но, на самом деле, они не "так доступны", как строки документов в python. Например, если у меня есть класс, и я хочу вывести документацию rdoc из класса, это довольно трудоемкая работа. Что я сделал, так это то, что я генерирую документацию, которую я пытаюсь сохранить up2date, а затем сам получаю эту информацию. Определенно, не до того же уровня, что и строки документации питона ..
rasjani

Строки документации могут быть использованы для обеспечения документооборота. Есть ли что-то подобное для Ruby?
Леннарт Регебро

2
Да, это называется "Ruby Doctest". Что касается doctests, все, что действительно важно, это то, что у вас есть где-то читаемая документация, которая включает фрагменты тестируемого кода - не имеет значения, находится ли она в строке документации или в комментарии.
Чак

5

Ruby имеет построчное зацикливание входных файлов (флаг '-n') из командной строки, поэтому его можно использовать как AWK. Это рубиновый лайнер:

ruby -ne 'END {puts $.}'

будет считать строки, как в одной строке AWK:

awk 'END{print NR}'

Ruby получает эту возможность через Perl, который использует AWK как способ получения системных администраторов вместе с Perl без необходимости менять способ их выполнения.


1
Я хотел бы добавить, что поддержка командной строки Python довольно слабая. Помимо отсутствующего автоматического цикла вы не можете поместить пару операторов в одну строку и передать их как аргумент командной строки в виде одной строки интерпретатору. По крайней мере, я не смог этого сделать.
ThomasH

Конечно вы можете. Но вам (как и на любом другом языке) нужно заключать в кавычки.
Леннарт Регебро

Python не предназначен для использования в командной строке, так как вы должны четко указать некоторые вещи (например, sys.stdin), если вы хотите использовать его таким образомpython -c "import sys; print len(list(sys.stdin))"
u0b34a0f6ae

5

У Руби есть сигилы и веточки, а у Питона нет.

Изменить : И одна очень важная вещь, которую я забыл (в конце концов, предыдущий был просто немного вспыхнуть :-p):

Python имеет JIT-компилятор ( Psyco ), немного более низкий уровень языка для написания более быстрого кода ( Pyrex ) и возможность добавлять встроенный код C ++ ( Weave ).


Правда, но это только синтаксис.
Леннарт Регебро

6
Ну, если вы хотите пойти по этому пути: оба завершены по Тьюрингу. Все остальное - просто синтаксис.
Йорг Миттаг

Да и разница в синтаксисе импорта ;-)
Fortran

1
Как это важно, если вы пишете @foo или self.foo?
Леннарт Регебро

1
@ Йорг: ОК, тогда называйте это чем-то иным, чем «синтаксис». Дело в том, что @foo и self.foo делают одно и то же, на самом деле это не функциональность, которую имеет Ruby, а Python - нет.
Леннарт Регебро

5

Мой питон ржавый, поэтому некоторые из них могут быть на питоне, и я просто не помню / никогда не учился во-первых, но вот первые несколько, о которых я подумал:

Пробелы

Руби обрабатывает пробелы совершенно иначе. Для начала вам не нужно ничего вставлять (это означает, что не имеет значения, используете ли вы 4 пробела или 1 табуляцию). Он также выполняет умное продолжение строки, поэтому действует следующее:

def foo(bar,
        cow)

По сути, если вы заканчиваете оператором, он выясняет, что происходит.

Примеси

В Ruby есть миксины, которые могут расширять экземпляры вместо полных классов:

module Humor
  def tickle
    "hee, hee!"
  end
end
a = "Grouchy"
a.extend Humor
a.tickle    »   "hee, hee!"

Перечисления

Я не уверен, что это то же самое, что генераторы, но в Ruby 1.9 ruby ​​как enums, так

>> enum = (1..4).to_enum
=> #<Enumerator:0x1344a8>

Ссылка: http://blog.nuclearsquid.com/writings/ruby-1-9-what-s-new-what-s-changed

"Аргументы по ключевым словам"

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

def foo(a, b=2, c=3)
  puts "#{a}, #{b}, #{c}"
end
foo(1,3)   >> 1, 3, 3
foo(1,c=5) >> 1, 5, 3
c          >> 5

Обратите внимание, что c = 5 фактически присваивает переменной c в вызывающей области значение 5, а параметру b - значение 5.

или вы можете сделать это с помощью хэшей, которые решают вторую проблему

def foo(a, others)
  others[:b] = 2 unless others.include?(:b)
  others[:c] = 3 unless others.include?(:c)
  puts "#{a}, #{others[:b]}, #{others[:c]}"
end
foo(1,:b=>3) >> 1, 3, 3
foo(1,:c=>5) >> 1, 2, 5

Ссылка: Прагматическое руководство Progammer по Ruby


Ваш второй пример foo (1, c = 5) не делает то, что вы думаете, он делает. Ruby не имеет именованных параметров.
скакун

5
Python имеет неявное продолжение строки в скобках (, [или{
u0b34a0f6ae

5

Вы можете иметь код в определении класса как на Ruby, так и на Python. Однако в Ruby у вас есть ссылка на класс (self). В Python у вас нет ссылки на класс, так как класс еще не определен.

Пример:

class Kaka
  puts self
end

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


Можете ли вы предоставить более подробную информацию (например, код) для вашего первого пункта?
Лоик Вольф

Пример кода - хорошая идея, я добавил это, хотя этот случай тривиален.
Леннарт Регебро

@SilentGhost: я не могу думать о том, что сейчас не совсем неясно. :)
Леннарт Регебро

Вы можете получить доступ к имени класса внутри класса в python: class foo (): def init __ (self): напечатать self .__ class .__ name__
txwikinger

1
@txwikinger: да, но не в теле класса, которое выполняется одновременно с classоператором.
Бастьен Леонар

4

Синтаксис не мелочь, он напрямую влияет на то, как мы думаем. Это также напрямую влияет на правила, которые мы создаем для систем, которые мы используем. В качестве примера у нас есть порядок операций из-за того, как мы пишем математические уравнения или предложения. Стандартные обозначения для математики позволяют людям читать ее более чем одним способом и получать разные ответы при одном и том же уравнении. Если бы мы использовали префиксную или постфиксную нотацию, мы бы создали правила, позволяющие различать, какими числами следует манипулировать, а не имели бы только правила для порядка вычисления значений.

Стандартные обозначения проясняют, о каких числах мы говорим, делая порядок их вычисления неоднозначным. Префиксная и постфиксная нотация делают порядок, в котором нужно вычислять простые данные, делая числа неоднозначными. В Python уже были бы многострочные лямбды, если бы не трудности, вызванные синтаксическим пробелом. (Предложения существуют для того, чтобы вытаскивать подобные вещи без обязательного добавления явных разделителей блоков.)

Я считаю, что проще писать условия, когда я хочу, чтобы что-то происходило, если условие ложно, гораздо проще написать с помощью оператора where в Ruby, чем семантически эквивалентной конструкции if-not в Ruby или других языках, например. Если большинство языков, которые люди используют сегодня, имеют одинаковую силу, как можно считать синтаксис каждого языка тривиальной вещью? После определенных функций, таких как блоки, механизмы наследования и т. Д., Синтаксис является наиболее важной частью языка, а не поверхностной.

Поверхностными являются эстетические качества красоты, которые мы приписываем синтаксису. Эстетика не имеет ничего общего с тем, как работает наше познание, а с синтаксисом.


Этот «комментарий» в три раза длиннее того, что разрешено в комментарии, независимо от респ.
Эндрю Гримм

На самом деле это кажется мне хорошим ответом. Отредактировал бит «это комментарий».
Билл Ящерица

3

Удивило, что ничего не упомянуло о механизме «отсутствия метода». Я бы привел примеры методов find_by _... в Rails, как пример возможностей этой языковой функции. Я предполагаю, что нечто подобное может быть реализовано в Python, но, насколько мне известно, изначально его там нет.


В Python есть get_attribute , который выполняет в основном то же самое, что метод method_missing в Ruby.
Мипади

3
Почему разработчики python всегда получают такую ​​задницу, когда ruby ​​упоминается где-нибудь? Вы не можете отрицать, что это не правда.
Аарона

method_missingможно эмулировать в Python в некоторых случаях: class M(): def __getattr__(self, n): return lambda: "Missing! " + n; M().hi(). Однако, есть небольшие различия, и я сомневаюсь, что это идиоматично в Python :-)

1
@DJTripleThreat: я отрицаю, что это правда.
Леннарт Регебро

3

Еще одно различие в лямбдах между Python и Ruby демонстрируется проблемой генератора Пола Грэма . Перепечатано здесь:

Напишите функцию foo, которая принимает число n и возвращает функцию, которая принимает число i и возвращает n, увеличенное на i. Примечание: (а) это число, а не целое число, (б) это увеличение на, а не плюс.

В Ruby вы можете сделать это:

def foo(n)
  lambda {|i| n += i }
end

В Python вы бы создали объект для хранения состояния n:

class foo(object):
    def __init__(self, n):
        self.n = n
    def __call__(self, i):
        self.n += i
        return self.n

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


3
Вы не можете увеличивать числа в Python, так что ограничение не имеет смысла. В Python числа неизменны. Если вместо этого мы изменим его на «плюс», класс не нужен. Следовательно, это не демонстрирует ничего о разнице лямбды, но различие в том, как работают числа. Если, конечно, вы не создадите изменяемый класс чисел. :)
Леннарт Регебро

2
Есть ограничение, чтобы уточнить желаемое поведение. Проблема заключается в следующем: f = foo (10) f (2) >> 12 f (3) >> 15 ... lambda {| i | n + i} дает: f = foo (10) f (2) >> 12 f (3) >> 13 ... Числа также неизменны в Ruby - например, вы не можете сказать 2 + = 1. И n + = 1 хорошо в обычной функции Python, но не лямбда. Так что дело в том, что такое «n», в том, что он создан, когда функция вызывается и лямбда формируется, что вы можете выполнять присваивание в лямбде (вместо просто выражений), и что оно может содержать значение n по нескольким звонкам.
dormsbee

Я не думаю, что вам нужно идти на такие длины в Python. Функции могут быть определены в других функциях. def foo(n): def f(i): return n + i return f,
FMC

2
Это все еще не то же самое, и ваш пример эквивалентен лямбде Python в комментарии выше. Версия Ruby создает лямбду, которая поддерживает состояние между вызовами. Приведенный вами пример позволяет настроить начальное значение для n, но функция, которую возвращает foo, всегда будет иметь это начальное значение. Версия Ruby увеличивается. Итак, скажем, f = foo (10). Версия Python: f (1) => 11, f (1) => 11. Версия Ruby f.call (1) => 11, f.call (1) => 12.
dormsbee

def foo(n): L=[n] def f(i): L[0] += i return L[0] return f, В Python3 вы можете использовать nonlocalключевое слово.
Jfs

3

Python назвал необязательные аргументы

def func(a, b=2, c=3):
    print a, b, c

>>> func(1)
1 2 3
>>> func(1, c=4)
1 2 4

AFAIK Ruby имеет только позиционированные аргументы, потому что b = 2 в объявлении функции - это аффект, который всегда добавляется.


3
Что означает "Ruby имеет только позиционированные аргументы, потому что b = 2 в объявлении функции - это аффект, который всегда добавляется", даже означает?
скакун

3
Не знаю, на какой планете вы живете, но def my_method(param1, optional = false)работает в Ruby 1.8.6, 1.8.7 и, предположительно, 1.9!
Роберт К

5
Злая Блоха и люди, которые проголосовали за его комментарий, вы не посмотрели на пример достаточно близко. Он может пропустить bпараметр в funcвызове, и он все еще поддерживает его значение по умолчанию. То есть bявляется вторым аргументом в сигнатуре, но он может пропустить его, добавив перед вторым параметром префикс c=. Ruby использует хеши для симуляции, но это не совсем то же самое.
2010 г.

2

Ruby имеет встроенную документацию:

 =begin

 You could use rdoc to generate man pages from this documentation

 =end

5
Строки документации заканчиваются как часть методов / классов, на которые вы их устанавливаете. Таким образом, вы можете сделать помощь (класс), и он покажет вам строки документов и т. Д.
Леннарт Регевро


2

В Ruby, когда вы импортируете файл с помощью require, все вещи, определенные в этом файле, окажутся в вашем глобальном пространстве имен.

С Cargo вы можете « требовать библиотеки, не загромождая пространство имен ».

# foo-1.0.0.rb
class Foo
  VERSION = "1.0.0"
end

# foo-2.0.0.rb
class Foo
  VERSION = "2.0.0"
end
>> Foo1 = import ("foo-1.0.0")
>> Foo2 = import ("foo-2.0.0")
>> Foo1 :: VERSION
=> "1.0.0"
>> Foo2 :: VERSION
=> "2.0.0"

Это должен был быть комментарий, а не новый ответ.
Леннарт Регебро
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.