Es gibt viele Diskussionen zwischen Python und Ruby, und ich finde sie alle völlig wenig hilfreich, weil sie sich alle umdrehen, warum Feature X die Sprache Y nervt oder die Behauptung, dass die Sprache Y kein X hat, obwohl dies tatsächlich der Fall ist. Ich weiß auch genau, warum ich Python bevorzuge, aber das ist auch subjektiv und würde niemandem bei der Auswahl helfen, da sie möglicherweise nicht den gleichen Geschmack in der Entwicklung haben wie ich.
Es wäre daher interessant, die Unterschiede objektiv aufzulisten. Also kein "Pythons Lambdas saugt". Erklären Sie stattdessen, was Rubys Lambdas können, was Pythons nicht kann. Keine Subjektivität. Beispielcode ist gut!
Bitte haben Sie nicht mehrere Unterschiede in einer Antwort. Und stimmen Sie diejenigen ab, von denen Sie wissen, dass sie richtig sind, und diejenigen, von denen Sie wissen, dass sie falsch (oder subjektiv) sind. Auch Unterschiede in der Syntax sind nicht interessant. Wir wissen, dass Python mit Einrückungen macht, was Ruby mit Klammern und Enden macht, und dass @ in Python selbst heißt.
UPDATE: Dies ist jetzt ein Community-Wiki, daher können wir hier die großen Unterschiede hinzufügen.
Ruby hat eine Klassenreferenz im Klassenkörper
In Ruby haben Sie einen Verweis auf die Klasse (self), die sich bereits im Klassenkörper befindet. In Python haben Sie erst nach Abschluss der Klassenkonstruktion einen Verweis auf die Klasse.
Ein Beispiel:
class Kaka
puts self
end
Selbst in diesem Fall ist die Klasse, und dieser Code würde "Kaka" ausdrucken. Es gibt keine Möglichkeit, den Klassennamen auszudrucken oder auf andere Weise über den Klassendefinitionskörper in Python (außerhalb von Methodendefinitionen) auf die Klasse zuzugreifen.
Alle Klassen sind in Ruby veränderbar
Auf diese Weise können Sie Erweiterungen für Kernklassen entwickeln. Hier ist ein Beispiel für eine Schienenverlängerung:
class String
def starts_with?(other)
head = self[0, other.length]
head == other
end
end
Python (stellen Sie sich vor, es gäbe keine ''.startswith
Methode):
def starts_with(s, prefix):
return s[:len(prefix)] == prefix
Sie können es für jede Sequenz verwenden (nicht nur für Zeichenfolgen). Um es zu verwenden, sollten Sie es explizit importieren, z from some_module import starts_with
.
Ruby verfügt über Perl-ähnliche Skriptfunktionen
Ruby verfügt über erstklassige Regexps, $ -Variablen, die zeilenweise awk / perl-Eingabeschleife und andere Funktionen, die es besser geeignet machen, kleine Shell-Skripte zu schreiben, die Textdateien mischen oder als Klebercode für andere Programme dienen.
Ruby hat erstklassige Fortsetzungen
Dank der callcc-Anweisung. In Python können Sie Fortsetzungen mit verschiedenen Techniken erstellen, die Sprache ist jedoch nicht unterstützt.
Ruby hat Blöcke
Mit der Anweisung "do" können Sie in Ruby eine mehrzeilige anonyme Funktion erstellen, die als Argument an die Methode vor do übergeben und von dort aufgerufen wird. In Python würden Sie dies stattdessen entweder durch Übergeben einer Methode oder mit Generatoren tun.
Rubin:
amethod { |here|
many=lines+of+code
goes(here)
}
Python (Ruby-Blöcke entsprechen verschiedenen Konstrukten in Python):
with amethod() as here: # `amethod() is a context manager
many=lines+of+code
goes(here)
Oder
for here in amethod(): # `amethod()` is an iterable
many=lines+of+code
goes(here)
Oder
def function(here):
many=lines+of+code
goes(here)
amethod(function) # `function` is a callback
Interessanterweise heißt die Convenience-Anweisung in Ruby zum Aufrufen eines Blocks "Yield", wodurch in Python ein Generator erstellt wird.
Rubin:
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("\n")
Python:
descriptions = (f.description() for f in mylist)
"\n".join(filter(len, descriptions))
Python verfügt über integrierte 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 und können in Ruby 1.9 Fasern als Generatoren verwendet werden, und die Enumerator-Klasse ist ein integrierter 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 mit den obigen Blockbeispielen.
Python verfügt über eine flexible Behandlung von Namensräumen
Wenn Sie in Ruby eine Datei mit importieren require
, werden alle in dieser Datei definierten Elemente in Ihrem globalen Namespace gespeichert. Dies führt zu einer Verschmutzung des Namespace. Die Lösung dafür sind Rubys-Module. Wenn Sie jedoch einen Namespace mit einem Modul erstellen, müssen Sie diesen Namespace verwenden, um auf die enthaltenen Klassen zuzugreifen.
In Python ist die Datei ein Modul, und Sie können die darin enthaltenen Namen mit importieren from themodule import *
, wodurch der Namespace verschmutzt wird, wenn Sie möchten. Sie können aber auch nur ausgewählte Namen mit importieren from themodule import aname, another
oder einfach import themodule
und dann auf die Namen mit zugreifen themodule.aname
. Wenn Sie mehr Ebenen in Ihrem Namespace wünschen, können Sie Pakete haben, die Verzeichnisse mit Modulen und einer __init__.py
Datei sind.
Python hat Docstrings
Docstrings sind Strings, 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 der automatischen Dokumentation.
def frobnicate(bar):
"""frobnicate takes a bar and frobnicates it
>>> bar = Bar()
>>> bar.is_frobnicated()
False
>>> frobnicate(bar)
>>> bar.is_frobnicated()
True
"""
Rubys Äquivalent ähnelt Javadocs und befindet sich über der Methode anstatt innerhalb dieser. Sie können zur Laufzeit aus den Dateien abgerufen werden, indem das Beispiel für die Methode # source_location von 1.9 verwendet wird
Python hat mehrere Vererbungen
Ruby nicht ("absichtlich" - siehe Rubys Website, hier erfahren Sie, wie es in Ruby gemacht wird ). Das Modulkonzept wird als eine Art abstrakter Klassen wiederverwendet.
Python hat Listen- / Dikt-Verständnis
Python:
res = [x*x for x in range(1, 10)]
Rubin:
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]
Rubin:
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'}
Rubin:
>> Hash[{1=>2, 3=>4}.map{|x,y| [x,(y*y).to_s]}]
=> {1=>"4", 3=>"16"}
Python hat Dekorateure
Dinge, die Dekorateuren ä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 Bereiche zu schließen, während Python nur Leerzeichen verwendet. In Ruby wurden kürzlich Versuche unternommen, nur Leerzeichen einzurücken. Http://github.com/michaeledgar/seamless