Il y a beaucoup de discussions sur Python vs Ruby, et je les trouve tous complètement inutiles, car ils tournent tous autour de la raison pour laquelle la fonctionnalité X aspire dans la langue Y, ou qui prétendent que la langue Y n'a pas X, bien qu'en fait, elle le soit. 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 en développement que moi.
Il serait donc intéressant d'énumérer objectivement les différences. Donc pas de "lambdas de Python craint". Expliquez plutôt ce que les lambdas de Ruby peuvent faire que Python ne peut pas. Aucune subjectivité. L'exemple de code est bon!
N'ayez pas plusieurs différences dans une réponse, s'il vous plaît. Et votez pour ceux que vous savez être corrects et pour ceux que vous savez incorrects (ou 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 crochets et les extrémités, et que @ est appelé self en Python.
MISE À JOUR: Ceci est maintenant un wiki communautaire, nous pouvons donc ajouter les grandes différences ici.
Ruby a une référence de classe dans le corps de classe
Dans Ruby, vous avez une référence à la classe (self) déjà dans le corps de la classe. En Python, vous n'avez pas de référence à la classe tant que la construction de la classe n'est pas terminée.
Un exemple:
class Kaka
puts self
end
self dans ce cas est la classe, et ce code afficherait "Kaka". Il n'y a aucun moyen d'imprimer le nom de la classe ou autrement d'accéder à la classe à partir du corps de définition de classe en Python (en dehors des définitions de méthode).
Toutes les classes sont modifiables en Ruby
Cela vous permet de développer des extensions pour les 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 de ''.startswith
méthode):
def starts_with(s, prefix):
return s[:len(prefix)] == prefix
Vous pouvez l'utiliser sur n'importe quelle séquence (pas seulement sur des 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 de type Perl
Ruby a des regexps de première classe, des variables $, la boucle d'entrée ligne par ligne awk / perl et d'autres fonctionnalités qui le rendent plus adapté à l'écriture de petits scripts shell qui fusionnent les fichiers texte ou agissent comme du code de collage pour d'autres programmes.
Ruby a des continuations de première classe
Merci à la déclaration callcc. En Python, vous pouvez créer des suites 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 multi-lignes dans Ruby, qui sera passée comme argument dans la méthode devant do, et appelée à partir de là. En Python, vous feriez plutôt cela 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 créera 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 plus facilement la programmation de style fonctionnel (de type pipe)
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 prend en charge les générateurs dans le langage. Dans Ruby 1.8, vous pouvez utiliser le module générateur qui utilise des continuations 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 des 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 aux exemples de blocs ci-dessus.
Python a une gestion flexible de l'espace de noms
Dans Ruby, lorsque vous importez un fichier avec require
, toutes les choses définies dans ce fichier se retrouveront dans votre espace de noms global. Cela provoque une 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 from themodule import *
, polluant ainsi l'espace de noms si vous le souhaitez. Mais vous pouvez également importer uniquement les noms sélectionnés avec from themodule import aname, another
ou vous pouvez simplement import themodule
accéder aux noms avec themodule.aname
. Si vous voulez plus de niveaux dans votre espace de noms, vous pouvez avoir des packages, qui sont des répertoires avec des modules et un __init__.py
fichier.
Python a des docstrings
Les docstrings sont des chaînes qui sont attachées aux modules, fonctions et méthodes et peuvent être examinées lors de l'exécution. Cela aide à créer des éléments tels 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 aux javadocs, et situé au-dessus de la méthode plutôt qu'en son sein. Ils peuvent être récupérés à l'exécution à partir des fichiers à l'aide de l' exemple de méthode # source_location de la méthode 1.9.
Python a un héritage multiple
Ruby ne le fait pas ("exprès" - voir le site Web de Ruby, voir ici comment cela se fait dans Ruby ). Il réutilise le concept de module comme un type de classes abstraites.
Python a des compréhensions list / dict
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 aux décorateurs peuvent également être créées dans Ruby, et on peut également affirmer qu'elles ne sont pas aussi nécessaires qu'en Python.
Différences de syntaxe
Ruby requiert "end" ou "}" pour fermer toutes ses étendues, tandis que Python utilise uniquement des espaces blancs. Il y a eu récemment des tentatives dans Ruby pour autoriser uniquement l'indentation des espaces blancs http://github.com/michaeledgar/seamless