python - used - who uses ruby




Was hat Ruby, was Python nicht hat und umgekehrt? (20)

In Ruby, when you import a file with require, all the things defined in that file will end up in your global namespace.

Mit Cargo Sie " Bibliotheken benötigen, ohne Ihren Namensraum zu überladen ".

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

Es gibt viele Diskussionen über Python vs Ruby, und ich finde sie alle nicht hilfreich, weil sie alle umdrehen, warum Feature X in der Sprache Y saugt, oder dass die Anspruchssprache 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 die Wahl erleichtern, da sie vielleicht nicht den gleichen Geschmack in der Entwicklung haben wie ich.

Es wäre daher interessant, die Unterschiede objektiv aufzuführen. Also keine "Pythons Lambdas saugt". Erklären Sie stattdessen, was Rubys Lambdas tun können, die Python nicht kann. Keine Subjektivität. Beispielcode ist gut!

Bitte haben Sie nicht mehrere Unterschiede in einer Antwort. Und wähle jene, von denen du weißt, dass sie richtig sind und diejenigen, die du kennst, falsch sind (oder subjektiv sind). Auch Unterschiede in der Syntax sind nicht interessant. Wir wissen, dass Python mit Einrückung tut, was Ruby mit Klammern und Enden macht, und dass @ in Python selbst heißt.

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

Ruby hat eine Klassenreferenz im Klassenkörper

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

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 auszugeben oder auf andere Weise über den Klassendefinitionskörper in Python auf die Klasse zuzugreifen (externe Methodendefinitionen).

Alle Klassen sind in Ruby änderbar

Dadurch können Sie Erweiterungen für Hauptklassen 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önnten es in jeder Sequenz (nicht nur Strings) verwenden. Um es zu verwenden, sollten Sie es explizit from some_module import starts_with .

Ruby hat Perl-ähnliche Skriptfunktionen

Ruby hat erste Klasse Regexps, $ -Variablen, die awk / perl Zeile für Zeile Eingabeschleife und andere Features, die es besser geeignet machen kleine Shellskripte zu schreiben, die Textdateien masern oder als Leimcode für andere Programme dienen.

Ruby hat erstklassige Fortsetzungen

Danke an die callcc-Anweisung. In Python können Sie Fortsetzungen mit verschiedenen Techniken erstellen, aber es ist keine Unterstützung in die Sprache integriert.

Ruby hat Blöcke

Mit der "do" -Anweisung können Sie eine mehrzeilige anonyme Funktion in Ruby erstellen, die als Argument in die Methode vor do übergeben und von dort aufgerufen wird. In Python würden Sie dies 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 wird die Convenience-Anweisung in Ruby zum Aufrufen eines Blocks "yield" genannt, was in Python einen Generator erzeugt.

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 Stil (Pipe-like) Programmierung einfacher

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

Python:

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

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

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! Außerdem sind in Ruby 1.9 Fibers Generatoren und können als Generatoren 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 mit den obigen Blockbeispielen.

Python hat flexible Namensraum-Handhabung

Wenn Sie in Ruby eine Datei mit require importieren, landen alle in dieser Datei definierten Dinge in Ihrem globalen Namensraum. Dies verursacht Namespace-Verschmutzung. Die Lösung dafür sind Rubys Module. Wenn Sie jedoch einen Namespace mit einem Modul erstellen, müssen Sie diesen Namespace für den Zugriff auf die enthaltenen Klassen verwenden.

In Python ist die Datei ein Modul, und Sie können ihre enthaltenen Namen from themodule import * , wodurch der Namespace bei from themodule import * verschmutzt wird. Sie können aber auch nur ausgewählte Namen from themodule import aname, another Sie from themodule import aname, another oder Sie können einfach das import themodule und dann auf die Namen mit der themodule.aname . Wenn Sie mehr Ebenen in Ihrem Namespace haben möchten, können Sie Pakete haben, die Verzeichnisse mit Modulen und einer __init__.py . __init__.py Datei sind.

Python hat Docstrings

Docstrings sind Strings, die an Module, Funktionen und Methoden angehängt sind und zur Laufzeit betrachtet werden können. Dies hilft beim Erstellen solcher Dinge wie dem Hilfe-Befehl 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
    """

Das Äquivalent von Ruby ähnelt Javadocs und befindet sich über der Methode statt innerhalb dieser. Sie können zur Laufzeit aus den Dateien abgerufen werden, indem Sie die Beispielmethode # source_location von 1.9 verwenden

Python hat mehrere Vererbungen

Ruby nicht ("absichtlich" - siehe Rubys Website, siehe hier, wie es in Ruby gemacht wird ). Es verwendet das Modulkonzept als eine Art abstrakter Klassen.

Python hat List / Dict-Comprehensions

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

Syntax Unterschiede

Ruby benötigt "end" oder "}", um alle seine Bereiche zu schließen, während Python nur Leerzeichen verwendet. Es gab in letzter Zeit Versuche in Ruby, Whitespace-Einzüge zuzulassen http://github.com/michaeledgar/seamless


Python Beispiel

Funktionen sind erstklassige Variablen in Python. Sie können eine Funktion deklarieren, als Objekt übergeben und überschreiben:

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

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

Dies ist ein grundlegendes Merkmal moderner Skriptsprachen. JavaScript und Lua machen das auch. Ruby behandelt Funktionen nicht auf diese Weise; Benennen einer Funktion ruft es auf.

Natürlich gibt es Möglichkeiten, diese Dinge in Ruby zu tun, aber sie sind keine erstklassigen Operationen. Zum Beispiel können Sie eine Funktion mit Proc.new umbrechen, um sie als Variable zu behandeln - aber dann ist es keine Funktion mehr; Es ist ein Objekt mit einer "Call" -Methode.

Rubys Funktionen sind keine erstklassigen Objekte

Ruby-Funktionen sind keine erstklassigen Objekte. Funktionen müssen in ein Objekt eingeschlossen werden, um sie herumzugeben; Das resultierende Objekt kann nicht wie eine Funktion behandelt werden. Funktionen können nicht in einer erstklassigen Weise zugewiesen werden; Stattdessen muss eine Funktion in ihrem Containerobjekt aufgerufen werden, um sie zu ändern.

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

Etwas mehr auf der Infrastrukturseite:

  • Python hat eine viel bessere Integration mit C ++ (über Dinge wie Boost.Python , SIP und Py++ ) als Ruby, wo die Optionen entweder direkt gegen die Ruby Interpreter API zu schreiben scheinen (was man natürlich auch mit Python machen kann) aber in beiden Fällen ist dies sehr niedrig, langwierig und fehleranfällig) oder SWIG verwenden (was zwar funktioniert und definitiv großartig ist, wenn Sie viele Sprachen unterstützen wollen, ist bei weitem nicht so schön wie Boost.Python oder SIP if Sie suchen speziell nach C ++).

  • Python hat eine Reihe von Webanwendungsumgebungen (Django, Pylons / Turbogears, web.py, wahrscheinlich mindestens ein halbes Dutzend anderer), während Ruby (effektiv) einen: Rails hat. (Andere Ruby-Web-Frameworks existieren zwar, aber es scheint schwierig zu sein, viel gegen Rails zu gewinnen). Ist dieser Aspekt gut oder schlecht? Schwer zu sagen und wahrscheinlich ziemlich subjektiv; Ich kann mir leicht Argumente vorstellen, dass die Python-Situation besser ist und dass die Ruby-Situation besser ist.

  • Kulturell scheinen die Python- und Ruby-Communities etwas anders zu sein, aber ich kann nur darauf hinweisen, da ich nicht so viel Erfahrung mit der Ruby-Community habe. Ich füge das hauptsächlich in der Hoffnung hinzu, dass jemand, der viel Erfahrung mit beiden hat, diese Aussage verstärken (oder ablehnen) kann.


Ich denke nicht "Ruby hat X und Python nicht, während Python Y und Ruby nicht hat" ist der nützlichste Weg, um es zu betrachten. Sie sind ziemlich ähnliche Sprachen mit vielen gemeinsamen Fähigkeiten.

Zu einem großen Teil ist der Unterschied, was die Sprache elegant und lesbar macht. Um ein Beispiel zu verwenden, das Sie angesprochen haben, haben beide theoretisch Lambdas, aber Python-Programmierer tendieren dazu, sie zu vermeiden, und Konstrukte, die mit ihnen erstellt wurden, sehen nicht annähernd so lesbar oder idiomatisch aus wie in Ruby. In Python wird also ein guter Programmierer einen anderen Weg einschlagen wollen, um das Problem zu lösen als in Ruby, nur weil es tatsächlich der bessere Weg ist, es zu tun.


Letztendlich werden alle Antworten auf einer bestimmten Ebene subjektiv sein, und die Antworten, die bisher gepostet wurden, beweisen ziemlich viel, dass man nicht auf ein Feature verweisen kann, das in der anderen Sprache nicht auf ebenso nette (wenn nicht ähnliche) Weise machbar ist , da beide Sprachen sehr prägnant und ausdrucksstark sind.

Ich mag Pythons Syntax. Allerdings müssen Sie ein bisschen tiefer graben als Syntax, um die wahre Schönheit von Ruby zu finden. In Rubys Konsistenz liegt zenlische Schönheit. Während kein triviales Beispiel dies vollständig erklären kann, werde ich versuchen, hier einen zu finden, nur um zu erklären, was ich meine.

Kehren Sie die Wörter in dieser Zeichenfolge um:

sentence = "backwards is sentence This"

Wenn Sie darüber nachdenken, wie Sie es tun würden, würden Sie Folgendes tun:

  1. Teilen Sie den Satz in Worte auf
  2. Kehren Sie die Wörter um
  3. Fügen Sie die Wörter wieder in eine Zeichenfolge ein

In Ruby würden Sie das tun:

sentence.split.reverse.join ' '

Genau wie du darüber nachdenkst, in der gleichen Reihenfolge, ruft eine Methode nach der anderen an.

In Python würde es eher so aussehen:

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

Es ist nicht schwer zu verstehen, aber es hat nicht den gleichen Fluss. Das Subjekt (der Satz) ist in der Mitte vergraben. Die Operationen sind eine Mischung aus Funktionen und Objektmethoden. Dies ist ein triviales Beispiel, aber man entdeckt viele verschiedene Beispiele, wenn man wirklich mit Ruby arbeitet und sie versteht, besonders bei nicht-trivialen Aufgaben.


Python hat eine "Wir sind alle Erwachsene hier" -Mentalität. So finden Sie, dass Ruby Dinge wie Konstanten hat, während Python dies nicht tut (obwohl Rubys Konstanten nur eine Warnung auslösen). Die Python-Art zu denken ist, dass, wenn Sie etwas konstant machen möchten, sollten Sie die Variablennamen in Großbuchstaben setzen und nicht ändern.

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

Ruby hat die Konzepte von Blöcken , die im Wesentlichen syntaktischer Zucker um einen Codeabschnitt sind; Sie sind eine Möglichkeit, Schließungen zu erstellen und sie an eine andere Methode weiterzugeben, die den Block möglicherweise verwendet oder nicht. Ein Block kann später über eine yield Anweisung aufgerufen werden.

Zum Beispiel kann eine einfache Definition einer each Methode auf Array etwas wie sein:

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

Dann kannst du das wie folgt aufrufen:

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

Python hat anonyme Funktionen / closures / lambdas, aber es hat nicht wirklich Blöcke, da es einige nützliche syntaktische Zucker fehlt. Es gibt jedoch mindestens einen Weg, um es ad hoc zu bekommen. Siehe hier zum Beispiel.


Sie können nur bestimmte Funktionen aus einem Modul in Python importieren. In Ruby importieren Sie die gesamte Liste der Methoden. Du könntest sie in Ruby "unimport", aber darum geht es nicht.

BEARBEITEN:

Nehmen wir dieses Ruby-Modul:


module Whatever
  def method1
  end

  def method2
  end
end

wenn Sie es in Ihren Code aufnehmen:


include Whatever

Sie werden sehen, dass sowohl method1 als auch method2 Ihrem Namespace hinzugefügt wurden. Sie können nicht nur Methode1 importieren. Entweder importieren Sie sie beide oder Sie importieren sie überhaupt nicht. In Python können Sie nur die Methoden Ihrer Wahl importieren. Wenn dies einen Namen hätte, würde man es vielleicht als selektiven Import bezeichnen?


Was Ruby über Python hat, sind seine Skriptsprachenfähigkeiten. Skriptsprache in diesem Kontext bedeutet, dass sie für "glue code" in Shell-Skripten und allgemeine Textmanipulation verwendet wird.

Diese werden meist mit Perl geteilt. Erstklassige eingebaute reguläre Ausdrücke, $ -Variablen, nützliche Kommandozeilenoptionen wie Perl (-a, -e) usw.

Zusammen mit seiner knappen, aber epxpressiven Syntax ist es perfekt für diese Art von Aufgaben geeignet.

Python ist für mich eher eine dynamisch typisierte Geschäftssprache, die sehr einfach zu erlernen ist und eine ordentliche Syntax hat. Nicht so "cool" wie Ruby aber ordentlich. Was Python für mich über Ruby hat, ist die große Anzahl von Bindungen für andere Bibliotheken. Bindungen an Qt und andere GUI-Bibliotheken, viele Spiel-Support-Bibliotheken und und und. Ruby hat viel weniger. Während viel verwendete Bindungen zB zu Datenbanken von guter Qualität sind, fand ich Nischen-Bibliotheken, die besser in Python unterstützt werden, selbst wenn für dieselbe Bibliothek auch eine Ruby-Bindung existiert.

Also würde ich sagen, dass beide Sprachen verwendet werden und es ist die Aufgabe, die definiert, welche zu verwenden ist. Beide sind leicht genug zu lernen. Ich benutze sie Seite an Seite. Ruby für Skripting und Python für eigenständige Anwendungen.



Schamlos kopieren / einfügen von: Alex Martelli Antwort auf " Was ist besser an Ruby als Python " Thread aus comp.lang.python Mailing-Liste.

18. August 2003, 10:50 Erik Max Francis schrieb:

"Brandon J. Van Every" schrieb:

Was ist besser an Ruby als an Python? Ich bin sicher, da ist etwas. Was ist es?

Wäre es nicht viel sinnvoller, Ruby Leute zu fragen, als Python Leute?

Abhängig von den Zielen - zum Beispiel, wenn der Zweck eine "soziologische Studie" der Python-Gemeinschaft enthält - kann es sein, dass Fragen an diese Gemeinschaft sich als aufschlußreicher erweisen, als Informationen an andere weiterzugeben :-).

Personally, I gladly took the opportunity to follow Dave Thomas' one-day Ruby tutorial at last OSCON. Below a thin veneer of syntax differences, I find Ruby and Python amazingly similar -- if I was computing the minimum spanning tree among just about any set of languages, I'm pretty sure Python and Ruby would be the first two leaves to coalesce into an intermediate node:-).

Sure, I do get weary, in Ruby, of typing the silly "end" at the end of each block (rather than just unindenting) -- but then I do get to avoid typing the equally-silly ':' which Python requires at the start of each block, so that's almost a wash:-). Other syntax differences such as '@foo' versus 'self.foo', or the higher significance of case in Ruby vs Python, are really just about as irrelevant to me.

Others no doubt base their choice of programming languages on just such issues, and they generate the hottest debates -- but to me that's just an example of one of Parkinson's Laws in action (the amount on debate on an issue is inversely proportional to the issue's actual importance).

Edit (by AM 6/19/2010 11:45): this is also known as "painting the bikeshed" (or, for short, "bikeshedding") -- the reference is, again, to Northcote Parkinson, who gave "debates on what color to paint the bikeshed" as a typical example of "hot debates on trivial topics". (end-of-Edit).

One syntax difference that I do find important, and in Python's favor -- but other people will no doubt think just the reverse -- is "how do you call a function which takes no parameters". In Python (like in C), to call a function you always apply the "call operator" -- trailing parentheses just after the object you're calling (inside those trailing parentheses go the args you're passing in the call -- if you're passing no args, then the parentheses are empty). This leaves the mere mention of any object, with no operator involved, as meaning just a reference to the object -- in any context, without special cases, exceptions, ad-hoc rules, and the like. In Ruby (like in Pascal), to call a function WITH arguments you pass the args (normally in parentheses, though that is not invariably the case) -- BUT if the function takes no args then simply mentioning the function implicitly calls it. This may meet the expectations of many people (at least, no doubt, those whose only previous experience of programming was with Pascal, or other languages with similar "implicit calling", such as Visual Basic) -- but to me, it means the mere mention of an object may EITHER mean a reference to the object, OR a call to the object, depending on the object's type -- and in those cases where I can't get a reference to the object by merely mentioning it I will need to use explicit "give me a reference to this, DON'T call it!" operators that aren't needed otherwise. I feel this impacts the "first-classness" of functions (or methods, or other callable objects) and the possibility of interchanging objects smoothly. Therefore, to me, this specific syntax difference is a serious black mark against Ruby -- but I do understand why others would thing otherwise, even though I could hardly disagree more vehemently with them:-).

Below the syntax, we get into some important differences in elementary semantics -- for example, strings in Ruby are mutable objects (like in C++), while in Python they are not mutable (like in Java, or I believe C#). Again, people who judge primarily by what they're already familiar with may think this is a plus for Ruby (unless they're familiar with Java or C#, of course:-). Me, I think immutable strings are an excellent idea (and I'm not surprised that Java, independently I think, reinvented that idea which was already in Python), though I wouldn't mind having a "mutable string buffer" type as well (and ideally one with better ease-of-use than Java's own "string buffers"); and I don't give this judgment because of familiarity -- before studying Java, apart from functional programming languages where all data are immutable, all the languages I knew had mutable strings -- yet when I first saw the immutable-string idea in Java (which I learned well before I learned Python), it immediately struck me as excellent, a very good fit for the reference-semantics of a higher level programming language (as opposed to the value-semantics that fit best with languages closer to the machine and farther from applications, such as C) with strings as a first-class, built-in (and pretty crucial) data type.

Ruby does have some advantages in elementary semantics -- for example, the removal of Python's "lists vs tuples" exceedingly subtle distinction. But mostly the score (as I keep it, with simplicity a big plus and subtle, clever distinctions a notable minus) is against Ruby (eg, having both closed and half-open intervals, with the notations a..b and a...b [anybody wants to claim that it's obvious which is which?-)], is silly -- IMHO, of course!). Again, people who consider having a lot of similar but subtly different things at the core of a language a PLUS, rather than a MINUS, will of course count these "the other way around" from how I count them:-).

Don't be misled by these comparisons into thinking the two languages are very different, mind you. They aren't. But if I'm asked to compare "capelli d'angelo" to "spaghettini", after pointing out that these two kinds of pasta are just about undistinguishable to anybody and interchangeable in any dish you might want to prepare, I would then inevitably have to move into microscopic examination of how the lengths and diameters imperceptibly differ, how the ends of the strands are tapered in one case and not in the other, and so on -- to try and explain why I, personally, would rather have capelli d'angelo as the pasta in any kind of broth, but would prefer spaghettini as the pastasciutta to go with suitable sauces for such long thin pasta forms (olive oil, minced garlic, minced red peppers, and finely ground anchovies, for example - but if you sliced the garlic and peppers instead of mincing them, then you should choose the sounder body of spaghetti rather than the thinner evanescence of spaghettini, and would be well advised to forego the achovies and add instead some fresh spring basil [or even -- I'm a heretic...! -- light mint...] leaves -- at the very last moment before serving the dish). Ooops, sorry, it shows that I'm traveling abroad and haven't had pasta for a while, I guess. But the analogy is still pretty good!-)

So, back to Python and Ruby, we come to the two biggies (in terms of language proper -- leaving the libraries, and other important ancillaries such as tools and environments, how to embed/extend each language, etc, etc, out of it for now -- they wouldn't apply to all IMPLEMENTATIONS of each language anyway, eg, Jython vs Classic Python being two implementations of the Python language!):

  1. Ruby's iterators and codeblocks vs Python's iterators and generators;

  2. Ruby's TOTAL, unbridled "dynamicity", including the ability
    to "reopen" any existing class, including all built-in ones, and change its behavior at run-time -- vs Python's vast but bounded dynamicity, which never changes the behavior of existing built-in classes and their instances.

Personally, I consider 1 a wash (the differences are so deep that I could easily see people hating either approach and revering the other, but on MY personal scales the pluses and minuses just about even up); and 2 a crucial issue -- one that makes Ruby much more suitable for "tinkering", BUT Python equally more suitable for use in large production applications. It's funny, in a way, because both languages are so MUCH more dynamic than most others, that in the end the key difference between them from my POV should hinge on that -- that Ruby "goes to eleven" in this regard (the reference here is to "Spinal Tap", of course). In Ruby, there are no limits to my creativity -- if I decide that all string comparisons must become case-insensitive, I CAN DO THAT ! Ie, I can dynamically alter the built-in string class so that a = "Hello World" b = "hello world" if a == b print "equal!\n" else print "different!\n" end WILL print "equal". In python, there is NO way I can do that. For the purposes of metaprogramming, implementing experimental frameworks, and the like, this amazing dynamic ability of Ruby is extremely appealing. BUT -- if we're talking about large applications, developed by many people and maintained by even more, including all kinds of libraries from diverse sources, and needing to go into production in client sites... well, I don't WANT a language that is QUITE so dynamic, thank you very much. I loathe the very idea of some library unwittingly breaking other unrelated ones that rely on those strings being different -- that's the kind of deep and deeply hidden "channel", between pieces of code that LOOK separate and SHOULD BE separate, that spells death in large-scale programming. By letting any module affect the behavior of any other "covertly", the ability to mutate the semantics of built-in types is just a BAD idea for production application programming, just as it's cool for tinkering.

If I had to use Ruby for such a large application, I would try to rely on coding-style restrictions, lots of tests (to be rerun whenever ANYTHING changes -- even what should be totally unrelated...), and the like, to prohibit use of this language feature. But NOT having the feature in the first place is even better, in my opinion -- just as Python itself would be an even better language for application programming if a certain number of built-ins could be "nailed down", so I KNEW that, eg, len("ciao") is 4 (rather than having to worry subliminally about whether somebody's changed the binding of name 'len' in the builtins module...). I do hope that eventually Python does "nail down" its built-ins.

But the problem's minor, since rebinding built-ins is quite a deprecated as well as a rare practice in Python. In Ruby, it strikes me as major -- just like the too powerful macro facilities of other languages (such as, say, Dylan) present similar risks in my own opinion (I do hope that Python never gets such a powerful macro system, no matter the allure of "letting people define their own domain-specific little languages embedded in the language itself" -- it would, IMHO, impair Python's wonderful usefulness for application programming, by presenting an "attractive nuisance" to the would-be tinkerer who lurks in every programmer's heart...).

Alex


Another difference in lambdas between Python and Ruby is demonstrated by Paul Graham's Accumulator Generator problem. Reprinted here:

Write a function foo that takes a number n and returns a function that takes a number i, and returns n incremented by i. Note: (a) that's number, not integer, (b) that's incremented by, not plus.

In Ruby, you can do this:

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

In Python, you'd create an object to hold the state of n:

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

Some folks might prefer the explicit Python approach as being clearer conceptually, even if it's a bit more verbose. You store state like you do for anything else. You just need to wrap your head around the idea of callable objects. But regardless of which approach one prefers aesthetically, it does show one respect in which Ruby lambdas are more powerful constructs than Python's.


I would like to mention Python descriptor API that allows one customize object-to-attribute "communication". It is also noteworthy that, in Python, one is free to implement an alternative protocol via overriding the default given through the default implementation of the __getattribute__ method. Let me give more details about the aforementioned. Descriptors are regular classes with __get__ , __set__ and/or __delete__ methods. When interpreter encounters something like anObj.anAttr , the following is performed:

  • __getattribute__ method of anObj is invoked
  • __getattribute__ retrieves anAttr object from the class dict
  • it checks whether abAttr object has __get__ , __set__ or __delete__ callable objects
  • the context (ie, caller object or class, and value, instead of the latter, if we have setter) is passed to the callable object
  • the result is returned.

As was mentioned, this is the default behavior. One is free to change the protocol by re-implementing __getattribute__ .

This technique is lot more powerful than decorators.


I'm unsure of this, so I add it as an answer first.

Python treats unbound methods as functions

That means you can call a method either like theobject.themethod() or by TheClass.themethod(anobject) .

Edit: Although the difference between methods and functions is small in Python, and non-existant in Python 3, it also doesn't exist in Ruby, simply because Ruby doesn't have functions. When you define functions, you are actually defining methods on Object.

But you still can't take the method of one class and call it as a function, you would have to rebind it to the object you want to call on, which is much more obstuse.


Python has docstrings and ruby doesn't... Or if it doesn't, they are not accessible as easily as in python.

Ps. If im wrong, pretty please, leave an example? I have a workaround that i could monkeypatch into classes quite easily but i'd like to have docstring kinda of a feature in "native way".


Ruby has a line by line loop over input files (the '-n' flag) from the commandline so it can be used like AWK. This Ruby one-liner:

ruby -ne 'END {puts $.}'

will count lines like the AWK one-liner:

awk 'END{print NR}'

Ruby gets feature this through Perl, which took it from AWK as a way of getting sysadmins on board with Perl without having to change the way they do things.


Ruby has embedded documentation:

 =begin

 You could use rdoc to generate man pages from this documentation

 =end

Ruby has sigils and twigils, Python doesn't.

Edit : And one very important thing that I forgot (after all, the previous was just to flame a little bit :-p):

Python has a JIT compiler ( Psyco ), a sightly lower level language for writing faster code ( Pyrex ) and the ability to add inline C++ code ( Weave ).


Syntax is not a minor thing, it has a direct impact on how we think. It also has a direct effect on the rules we create for the systems we use. As an example we have the order of operations because of the way we write mathematical equations or sentences. The standard notation for mathematics allows people to read it more than one way and arrive at different answers given the same equation. If we had used prefix or postfix notation we would have created rules to distinguish what the numbers to be manipulated were rather than only having rules for the order in which to compute values.

The standard notation makes it plain what numbers we are talking about while making the order in which to compute them ambiguous. Prefix and postfix notation make the order in which to compute plain while making the numbers ambiguous. Python would already have multiline lambdas if it were not for the difficulties caused by the syntactic whitespace. (Proposals do exist for pulling this kind of thing off without necessarily adding explicit block delimiters.)

I find it easier to write conditions where I want something to occur if a condition is false much easier to write with the unless statement in Ruby than the semantically equivalent "if-not" construction in Ruby or other languages for example. If most of the languages that people are using today are equal in power, how can the syntax of each language be considered a trivial thing? After specific features like blocks and inheritance mechanisms etc. syntax is the most important part of a language,hardly a superficial thing.

What is superficial are the aesthetic qualities of beauty that we ascribe to syntax. Aesthetics have nothing to do with how our cognition works, syntax does.


You can have code in the class definition in both Ruby and Python. However, in Ruby you have a reference to the class (self). In Python you don't have a reference to the class, as the class isn't defined yet.

Ein Beispiel:

class Kaka
  puts self
end

self in this case is the class, and this code would print out "Kaka". There is no way to print out the class name or in other ways access the class from the class definition body in Python.







ruby