Was hat Ruby, was Python nicht hat und umgekehrt?

| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |

Es gibt viele Diskussionen über Python vs. Ruby, und ich finde sie alle völlig wenig hilfreich, weil sie sich alle umdrehen, warum Merkmal X in Sprache Y scheiße ist, oder dass behauptet wird, dass Sprache Y kein X hat, obwohl es tatsächlich so ist Ich weiß auch genau, warum ich Python bevorzuge, aber das ist auch subjektiv und würde niemandem bei der Auswahl helfen, da er vielleicht nicht den gleichen Geschmack in der Entwicklung hat wie ich.

Das würde es daher Es wäre interessant, die Unterschiede objektiv aufzulisten. Also keine Lambdas von "Python". Erklären Sie stattdessen, was Rubys Lambdas können, was Pythons nicht können. Keine Subjektivität. Beispielcode ist gut!

Bitte nicht mehrere Unterschiede in einer Antwort haben. Und stimmen Sie diejenigen ab, von denen Sie wissen, dass sie richtig sind, und abwärts diejenigen, von denen Sie wissen, dass sie falsch sind (oder subjektiv sind). Auch Unterschiede in der Syntax sind nicht interessant. Wir wissen, dass Python mit Einrückungen das macht, was Ruby mit Klammern und Enden macht, und dass @ in Python self heißt.

UPDATE: Dies ist jetzt ein Community-Wiki, also können wir hier die großen Unterschiede hinzufügen.

p>

Ruby hat eine Klassenreferenz im Klassenkörper

In Ruby haben Sie bereits eine Referenz auf die Klasse (selbst) im Klassenkörper. In Python haben Sie keinen Verweis auf die Klasse, bis die Klassenkonstruktion abgeschlossen ist.

Ein Beispiel:

Klasse Kaka fügt sich selbst hinzu 

self ist in diesem Fall die Klasse, und dieser Code würde "Kaka" ausgeben. Es gibt keine Möglichkeit, den Klassennamen auszudrucken oder auf andere Weise auf die Klasse vom Klassendefinitionskörper in Python (außerhalb Methodendefinitionen).

Alle Klassen sind in Ruby änderbar

Damit können Sie Erweiterungen für Kernklassen entwickeln. Hier ist ein Beispiel für eine Rails-Erweiterung:

 class String def starts_with?(other) head = self[0, other.length] head == other end end 

Python (stellen Sie sich vor, es gäbe kein "". startswith method):

def starts_with(s, prefix): return s[:len(prefix)] == prefix 

Du könnte es für jede Sequenz verwenden (nicht nur für Zeichenfolgen). Um es zu verwenden, sollten Sie es explizit importieren, zB from some_module import started_with.

Ruby hat Perl-ähnliche Skriptfunktionen

Ruby hat erstklassige Regexps, $-Variablen, die awk/perl-Zeile-für-Zeile-Eingabeschleife und andere Features, die es besser geeignet machen, kleine Shell-Skripte zu schreiben, die Textdateien mungen oder als Glue-Code für andere Programme dienen.

Ruby hat erstklassige Fortsetzungen

Dank der callcc-Anweisung. In Python können Sie Fortsetzungen durch verschiedene Techniken erstellen, aber es gibt keine in die Sprache eingebaute Unterstützung.

Ruby hat Blöcke

Mit der "do"-Anweisung können Sie eine Multi- line anonyme Funktion in Ruby, die als Argument an die Methode vor do übergeben und von dort aufgerufen wird. In Python würden Sie dies stattdessen entweder durch Übergabe einer Methode oder mit Generatoren tun.

Ruby:

amethod { |here| viele=Zeilen+von+Code geht(hier) } 

Python (Ruby-Blöcke entsprechen verschiedenen Konstrukten in Python):

mit amethod() als hier: # `amethod() ist ein Kontextmanager viele=Zeilen+von+Code geht(hier) 

Oder

für hier in amethod() : # `amethod()` ist eine iterierbare viele=Zeilen+von+Code geht(hier) 

Oder

def function(hier): many =lines+of+code goes(hier) amethod(function) # `function` ist ein Callback 

Interessanterweise heißt die Convenience-Anweisung in Ruby zum Aufrufen eines Blocks "yield", was in Python erstellt einen Generator.

Ruby:

def themethod yield 5 end themethod do |foo| puts foo end 

Python:

def themethod(): yield 5 for foo in themethod(): print foo 

Obwohl die Prinzipien unterschiedlich sind, ist das Ergebnis auffallend ähnlich.

Ruby unterstützt die funktionale (pipe-ähnliche) Programmierung einfacher

myList.map(& :description).reject(&:empty?).join(" ") 

Python:

descriptions = (f.description() for f in mylist) " ".join(filter(len, descriptions)) 

Python hat eingebaute Generatoren (die wie oben erwähnt wie Ruby-Blöcke verwendet werden)

Python unterstützt Generatoren in der Sprache. In Ruby 1.8 können Sie das Generatormodul verwenden, das Fortsetzungen verwendet, um einen Generator aus einem Block zu erstellen. Oder Sie könnten einfach einen Block/Proc/Lambda verwenden! Darüber hinaus sind Fibers in Ruby 1.9 Generatoren und können als solche verwendet werden, und die Enumerator-Klasse ist ein eingebauter Generator 4

docs.python. org hat dieses Generatorbeispiel:

def reverse(data): for index in range(len(data)-1, -1, -1): yield data[index] 

Vergleichen Sie dies den obigen Blockbeispielen.

Python hat eine flexible Namensraumbehandlung

Wenn Sie in Ruby eine Datei mit require, landen alle Dinge, die in dieser Datei definiert sind, in Ihrem globalen Namensraum. Dies verursacht Namespace-Verschmutzung. Die Lösung dafür sind Rubys-Module. Aber wenn Sie einen Namensraum mit einem Modul erstellen, dann müssen Sie diesen Namensraum verwenden, um auf die enthaltenen Klassen zuzugreifen.

In Python ist die Datei ein Modul, und Sie können die enthaltenen Namen mit importieren aus dem Modul import *, wodurch der Namensraum verunreinigt wird, wenn Sie möchten. Sie können aber auch nur ausgewählte Namen mit from themodule import aname, another importieren oder Sie können einfach dasModul importieren und dann mit themodule.aname auf die Namen zugreifen >. Wenn Sie mehr Ebenen in Ihrem Namensraum haben möchten, können Sie Pakete haben, die Verzeichnisse mit Modulen und einer __init__.py-Datei sind.

Python hat Docstrings

Docstrings sind Zeichenfolgen, die an Module, Funktionen und Methoden angehängt sind und zur Laufzeit überprüft werden können. Dies hilft beim Erstellen von Dingen wie dem Hilfebefehl und automatischer Dokumentation.

def frobnicate(bar): """frobnicate nimmt einen Balken und frobnicate ihn >>> bar = Bar( ) >>> bar.is_frobnicated() Falsch >>> frobnicate(bar) >>> bar.is_frobnicated() Wahr """ 

Ruby "s-Äquivalente ähneln javadocs und befinden sich oberhalb der Methode statt innerhalb. Sie können zur Laufzeit aus den Dateien abgerufen werden, indem die Method#source_location von 1.9 verwendet wird Beispielverwendung

Python hat Mehrfachvererbung

Ruby nicht ("absichtlich" -- siehe Rubys Website, sehen Sie hier, wie es geht "ist in Ruby). Es verwendet das Modulkonzept als eine Art von abstrakten Klassen wieder.

Python hat List/Dict Comprehensions

Python:

res = [x* x für x im Bereich (1, 10)] 

Ruby:

res = (0..9).map { |x| x * x } 

Python:

>>> (x*x für x im Bereich (10)) <Generatorobjekt <genexpr> bei 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) für x,y in {1:2, 3:4}.items()} {1: "4", 3: "16"} 

Rubin:

>> Hash[{1=>2, 3=>4}.map{|x,y| [x,(y*y).to_s]}] => {1=>"4", 3=>"16"} 

Python hat Dekoratoren

Dinge, die Dekoratoren ähnlich sind, können auch in Ruby erstellt werden, und es kann auch argumentiert werden, dass sie nicht so notwendig sind wie in Python.

Syntaxunterschiede

Ruby benötigt "end" oder "}", um alle seine Gültigkeitsbereiche zu schließen, während Python verwendet nur Leerzeichen. Es gab kürzlich Versuche in Ruby, Einrückungen nur mit Leerzeichen zuzulassen http://github.com /michaeledgar/seamless