ruby ou python




Qu'est-ce que Ruby a que Python n'a pas, et vice versa? (20)

Il y a beaucoup de discussions sur Python et Ruby, et je les trouve complètement inutiles, parce que tout tourne autour du fait que la fonctionnalité X suce dans la langue Y, ou que le langage de revendication Y n'a pas X, bien qu'en fait. Je sais aussi exactement pourquoi je préfère Python, mais c'est aussi subjectif, et cela n'aiderait personne à choisir, car ils pourraient ne pas avoir les mêmes goûts de développement que moi.

Il serait donc intéressant d'énumérer les différences, objectivement. Donc pas de "lambdas de Python". Expliquez plutôt ce que les lambdas de Ruby peuvent faire, ce que Python ne peut pas faire. Aucune subjectivité. Exemple de code est bon!

Ne pas avoir plusieurs différences dans une réponse, s'il vous plaît. Et votez pour ceux que vous connaissez sont corrects, et vers le bas ceux que vous connaissez sont incorrects (ou sont subjectifs). De plus, les différences de syntaxe ne sont pas intéressantes. Nous savons que Python fait avec indentation ce que Ruby fait avec les parenthèses et les extrémités, et que @ est appelé self dans Python.

MISE À JOUR: Ceci est maintenant un wiki communautaire, donc nous pouvons ajouter les grandes différences ici.

Ruby a une référence de classe dans le corps de la classe

Dans Ruby, vous avez déjà une référence à la classe (self) dans le corps de la classe. En Python, vous n'avez pas de référence à la classe avant la fin de la construction de la classe.

Un exemple:

class Kaka
  puts self
end

Dans ce cas, c'est la classe, et ce code afficherait "Kaka". Il n'existe aucun moyen d'imprimer le nom de la classe ou d'accéder autrement à la classe à partir du corps de définition de classe en Python (en dehors des définitions de méthodes).

Toutes les classes sont modifiables dans Ruby

Cela vous permet de développer des extensions aux classes principales. Voici un exemple d'extension de rails:

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

Python (imaginez qu'il n'y avait pas ''.startswith méthode ''.startswith ):

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

Vous pouvez l'utiliser sur n'importe quelle séquence (pas seulement les chaînes). Pour l'utiliser, vous devez l'importer explicitement, par exemple à from some_module import starts_with .

Ruby a des fonctionnalités de script similaires à Perl

Ruby a des regexps de première classe, $ -variables, la ligne awk / perl par ligne d'entrée et d'autres fonctionnalités qui le rendent plus adapté à l'écriture de petits scripts shell qui modifient les fichiers texte ou servent de code de collage pour d'autres programmes.

Ruby a des suites de première classe

Merci à la déclaration callcc. En Python, vous pouvez créer des continuations par diverses techniques, mais il n'y a pas de support intégré au langage.

Ruby a des blocs

Avec l'instruction "do", vous pouvez créer une fonction anonyme multiligne dans Ruby, qui sera passée en argument dans la méthode devant do, et appelée à partir de là. En Python, vous le feriez plutôt en passant une méthode ou avec des générateurs.

Rubis:

amethod { |here|
    many=lines+of+code
    goes(here)
}

Python (les blocs Ruby correspondent à différentes constructions en Python):

with amethod() as here: # `amethod() is a context manager
    many=lines+of+code
    goes(here)

Ou

for here in amethod(): # `amethod()` is an iterable
    many=lines+of+code
    goes(here)

Ou

def function(here):
    many=lines+of+code
    goes(here)

amethod(function)     # `function` is a callback

Fait intéressant, l'instruction de commodité dans Ruby pour appeler un bloc est appelée "yield", ce qui en Python va créer un générateur.

Rubis:

def themethod
    yield 5
end

themethod do |foo|
    puts foo
end

Python:

def themethod():
    yield 5

for foo in themethod():
    print foo

Bien que les principes soient différents, le résultat est étonnamment similaire.

Ruby prend en charge la programmation de style fonctionnel (comme un tuyau) plus facilement

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

Python:

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

Python a des générateurs intégrés (qui sont utilisés comme des blocs Ruby, comme indiqué ci-dessus)

Python a un support pour les générateurs dans la langue. Dans Ruby 1.8, vous pouvez utiliser le module générateur qui utilise des suites pour créer un générateur à partir d'un bloc. Ou, vous pouvez simplement utiliser un bloc / proc / lambda! De plus, dans Ruby 1.9, les fibres sont et peuvent être utilisées comme générateurs, et la classe Enumerator est un générateur intégré 4

docs.python.org a cet exemple de générateur:

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

Comparez cela avec les exemples de blocs ci-dessus.

Python a une gestion flexible de l'espace de nom

Dans Ruby, lorsque vous importez un fichier avec require , toutes les choses définies dans ce fichier finiront dans votre espace de noms global. Cela provoque la pollution de l'espace de noms. La solution à cela est les modules Rubys. Mais si vous créez un espace de noms avec un module, vous devez utiliser cet espace de noms pour accéder aux classes contenues.

En Python, le fichier est un module, et vous pouvez importer ses noms contenus avec l' from themodule import * , polluant ainsi l'espace de noms si vous le souhaitez. Mais vous pouvez également importer seulement les noms sélectionnés avec l' from themodule import aname, another ou vous pouvez simplement import themodule et ensuite accéder aux noms avec themodule.aname . Si vous voulez plus de niveaux dans votre espace de noms, vous pouvez avoir des paquets, qui sont des répertoires avec des modules et un fichier __init__.py .

Python a des docstrings

Les Doctrings sont des chaînes attachées à des modules, des fonctions et des méthodes et peuvent être introspectées lors de l'exécution. Cela aide à créer des choses telles que la commande d'aide et la documentation automatique.

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

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

L'équivalent de Ruby est similaire à javadocs, et situé au-dessus de la méthode au lieu de l'intérieur. Ils peuvent être récupérés au moment de l'exécution à partir des fichiers en utilisant l' exemple de la méthode n ° # source_location.

Python a plusieurs héritages

Ruby ne le fait pas ("volontairement" - voir le site web de Ruby, voir ici comment ça se passe dans Ruby ). Il réutilise le concept de module en tant que type de classes abstraites.

Python a des listes / dictées

Python:

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

Rubis:

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]

Rubis:

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

Rubis:

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

Python a des décorateurs

Des choses similaires à des décorateurs peuvent aussi être créées dans Ruby, et on peut aussi argumenter qu'elles ne sont pas aussi nécessaires qu'en Python.

Différences de syntaxe

Ruby requiert "end" ou "}" pour fermer toutes ses étendues, alors que Python n'utilise que des espaces blancs. Il y a eu des tentatives récentes dans Ruby pour permettre l'indentation seulement http://github.com/michaeledgar/seamless


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

Avec Cargo vous pouvez " exiger des bibliothèques sans encombrer votre espace de noms ".

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

Exemple de Python

Les fonctions sont des variables de première classe en Python. Vous pouvez déclarer une fonction, la transmettre comme un objet et l'écraser:

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

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

C'est une caractéristique fondamentale des langages de script modernes. JavaScript et Lua le font aussi. Ruby ne traite pas les fonctions de cette façon; nommer une fonction l'appelle.

Bien sûr, il y a des façons de faire ces choses dans Ruby, mais ce ne sont pas des opérations de première classe. Par exemple, vous pouvez envelopper une fonction avec Proc.new pour la traiter comme une variable - mais alors ce n'est plus une fonction; c'est un objet avec une méthode "call".

Les fonctions de Ruby ne sont pas des objets de première classe

Les fonctions Ruby ne sont pas des objets de première classe. Les fonctions doivent être enveloppées dans un objet pour les faire circuler; l'objet résultant ne peut pas être traité comme une fonction. Les fonctions ne peuvent pas être attribuées de manière privilégiée; à la place, une fonction dans son objet conteneur doit être appelée pour les modifier.

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

Ce que Ruby a sur Python, ce sont ses capacités de langage de script. Le langage de script dans ce contexte signifie être utilisé pour le "code de collage" dans les scripts shell et la manipulation générale du texte.

Ceux-ci sont principalement partagés avec Perl. Expressions régulières intégrées de première classe, $ -Variables, options de ligne de commande utiles comme Perl (-a, -e), etc.

Avec sa syntaxe concise mais épaisse, il est parfait pour ce genre de tâches.

Pour moi, Python est plus un langage d'affaires dynamiquement typé, très facile à apprendre et doté d'une syntaxe soignée. Pas aussi "cool" que Ruby mais soigné. Ce que Python a sur Ruby pour moi, c'est le grand nombre de liaisons pour les autres bibliothèques. Liaisons vers Qt et d'autres bibliothèques GUI, de nombreuses bibliothèques de support de jeu et et et. Ruby a beaucoup moins. Tandis que beaucoup de liaisons utilisées par exemple pour les bases de données sont de bonne qualité, j'ai trouvé que les librairies de niche étaient mieux supportées en Python même si pour la même bibliothèque il y avait aussi une liaison Ruby.

Donc, je dirais que les deux langues ont son utilité et que c'est la tâche qui définit laquelle utiliser. Les deux sont assez faciles à apprendre. Je les utilise côte à côte. Ruby pour les scripts et Python pour les applications autonomes.


En fin de compte, toutes les réponses seront subjectives à un certain niveau, et les réponses publiées jusqu'à présent prouvent à peu près que vous ne pouvez pas pointer vers une caractéristique qui n'est pas faisable dans l'autre langue d'une manière tout aussi agréable (sinon similaire) , puisque les deux langues sont très concises et expressives.

J'aime la syntaxe de Python. Cependant, vous devez creuser un peu plus profond que la syntaxe pour trouver la vraie beauté de Ruby. Il y a une beauté zen dans la consistance de Ruby. Bien qu'aucun exemple trivial ne puisse l'expliquer complètement, je vais essayer d'en trouver un juste pour expliquer ce que je veux dire.

Inversez les mots de cette chaîne:

sentence = "backwards is sentence This"

Quand vous pensez à la façon dont vous le feriez, vous feriez ce qui suit:

  1. Diviser la phrase en mots
  2. Inversez les mots
  3. Re-joindre les mots dans une chaîne

Dans Ruby, vous feriez ceci:

sentence.split.reverse.join ' '

Exactement comme vous y pensez, dans la même séquence, une méthode appelle après l'autre.

En python, cela ressemblerait plus à ceci:

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

Ce n'est pas difficile à comprendre, mais ça n'a pas tout à fait le même flux. Le sujet (la phrase) est enterré au milieu. Les opérations sont un mélange de fonctions et de méthodes d'objets. Ceci est un exemple trivial, mais on découvre beaucoup d'exemples différents quand on travaille vraiment avec Ruby et qu'on le comprend, spécialement sur des tâches non triviales.


Je voudrais suggérer une variante de la question initiale: "Qu'est-ce que Ruby a ce Python, et vice versa?" qui admet la réponse décevante, "Eh bien, que pouvez-vous faire avec Ruby ou Python qui ne peut pas être fait dans Intercal?" Rien à ce niveau, car Python et Ruby font tous deux partie de la vaste famille royale assise sur le trône d'être Turing approximant.

Mais qu'en est-il de ceci:

Qu'est-ce qui peut être fait avec élégance et bien en Python qui ne peut pas être fait en Ruby avec une telle beauté et une bonne ingénierie, ou vice versa?

Cela peut être beaucoup plus intéressant que la simple comparaison de caractéristiques.


Python a une mentalité "nous sommes tous des adultes ici". Ainsi, vous trouverez que Ruby a des constantes alors que Python ne le fait pas (bien que les constantes de Ruby ne déclenchent qu'un avertissement). La façon de penser de Python est que si vous voulez faire quelque chose de constant, vous devriez mettre les noms des variables dans toutes les majuscules et ne pas les changer.

Par exemple, 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 a les concepts de blocs , qui sont essentiellement du sucre syntaxique autour d'une section de code; ils sont un moyen de créer des fermetures et de les passer à une autre méthode qui peut ou non utiliser le bloc. Un bloc peut être invoqué plus tard via une déclaration de yield .

Par exemple, une définition simple d'une méthode sur Array peut être quelque chose comme:

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

Alors vous pouvez invoquer ceci comme ceci:

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

Python a des fonctions / fermetures / lambdas anonymes, mais il n'a pas tout à fait des blocs car il manque une partie du sucre syntaxique utile. Cependant, il existe au moins une façon de l'obtenir de manière ad hoc. Voir, par exemple, here .


Sur le website de Ruby:

Similitudes Comme avec Python, en Ruby, ...

  • Il y a une invite interactive (appelée irb).
  • Vous pouvez lire les docs sur la ligne de commande (avec la commande ri au lieu de pydoc).
  • Il n'y a pas de terminaison de ligne spéciale (sauf la nouvelle ligne habituelle).
  • Les littéraux de chaîne peuvent s'étendre sur plusieurs lignes, comme les chaînes à guillemets simples de Python.
  • Les parenthèses sont pour les listes, et les accolades sont pour les dicts (qui, dans Ruby, sont appelés "hashs").
  • Les tableaux fonctionnent de la même façon (les ajouter fait un long tableau, mais les composer comme ceci a3 = [ a1, a2 ] vous donne un tableau de tableaux).
  • Les objets sont fortement et dynamiquement typés.
  • Tout est un objet, et les variables ne sont que des références à des objets.
  • Bien que les mots-clés soient un peu différents, les exceptions fonctionnent à peu près de la même manière.
  • Vous avez des outils doc intégrés (Ruby est appelé rdoc).

Différences Contrairement à Python, en Ruby, ...

  • Les chaînes sont mutables.
  • Vous pouvez créer des constantes (variables dont vous n'avez pas l'intention de modifier la valeur).
  • Il existe des conventions de cas appliquées (les noms de classe commencent par une lettre majuscule, les variables commencent par une lettre minuscule).
  • Il n'y a qu'un seul type de conteneur de liste (un tableau), et il est mutable.
  • Les chaînes entre guillemets permettent des séquences d'échappement (comme \ t) et une syntaxe spéciale de "substitution d'expression" (qui vous permet d'insérer directement les résultats des expressions Ruby dans d'autres chaînes sans "ajouter" + "chaînes" + "ensemble") . Les chaînes à guillemets simples sont comme les «chaînes brutes» de Python.
  • Il n'y a pas de classes "nouveau style" et "ancien style". Juste un genre.
  • Vous n'accédez jamais directement aux attributs. Avec Ruby, c'est tous les appels de méthode.
  • Les parenthèses pour les appels de méthodes sont généralement facultatives.
  • Il y a un accès public, privé et protégé pour faire respecter l'accès, au lieu du _voluntary_ underscore __convention__ de _voluntary_ underscore __convention__ de Python.
  • "Mixin's" sont utilisés à la place de l'héritage multiple.
  • Vous pouvez ajouter ou modifier les méthodes des classes intégrées. Les deux langages vous permettent d'ouvrir et de modifier des classes à tout moment, mais Python empêche la modification des built-ins - ce n'est pas le cas de Ruby.
  • Vous avez vrai et faux au lieu de Vrai et Faux (et nul au lieu de Aucun).
  • Lorsque testé pour la vérité, seulement faux et nul évaluer à une valeur fausse. Tout le reste est vrai (y compris 0, 0.0, "" et []).
  • C'est elsif au lieu de elif.
  • C'est nécessaire au lieu d'importer. Sinon, l'utilisation est la même.
  • Les commentaires de style habituel sur la ligne (s) au-dessus des choses (au lieu de docstrings ci-dessous) sont utilisés pour générer des documents.
  • Il y a un certain nombre de raccourcis qui, bien que vous en donniez plus à retenir, vous apprennent rapidement. Ils ont tendance à rendre Ruby amusant et très productif.

Vous pouvez importer uniquement des fonctions spécifiques d'un module en Python. Dans Ruby, vous importez toute la liste des méthodes. Vous pourriez les "désimporter" dans Ruby, mais ce n'est pas ce dont il s'agit.

MODIFIER:

Prenons ce module Ruby:


module Whatever
  def method1
  end

  def method2
  end
end

si vous l'incluez dans votre code:


include Whatever

vous verrez que method1 et method2 ont été ajoutées à votre espace de noms. Vous ne pouvez pas importer seulement la méthode1 . Vous les importez tous les deux ou vous ne les importez pas du tout. En Python, vous pouvez importer uniquement les méthodes de votre choix. Si cela avait un nom, peut-être cela s'appellerait l'importation sélective?



Copier / coller sans vergogne de: Alex Martelli répondre sur le fil " Quoi de mieux sur Ruby que Python " de la liste de diffusion comp.lang.python .

18 août 2003, 10:50 Erik Max Francis a écrit:

"Brandon J. Van Every" a écrit:

Quoi de mieux sur Ruby que sur Python? Je suis sûr qu'il y a quelque chose. Qu'Est-ce que c'est?

Ne serait-il pas plus logique de demander cela aux gens de Ruby, plutôt qu'aux gens de Python?

Peut-être, ou non, en fonction de ses objectifs - par exemple, si ses objectifs comprennent une «étude sociologique» de la communauté Python, alors poser des questions à cette communauté est susceptible de révéler plus d'informations à ce sujet, que de les mettre ailleurs :-).

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.

Un exemple:

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