web-dev-qa-db-fra.com

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

Il y a beaucoup de discussions sur Python vs Ruby, et je les trouve toutes complètement inutiles, car elles renversent toutes les raisons pour lesquelles la fonctionnalité X est foutue dans la langue Y, ou que la langue revendiquée Y n'a pas X, bien que en fait c'est le cas. Je sais aussi exactement pourquoi je préfère Python, mais c’est aussi subjectif et cela n’aidera personne, car il n’a peut-être pas les mêmes goûts en matière de développement que moi.

Il serait donc intéressant d’énumérer les différences de manière objective. Donc pas de "lambdas de Python est nul". Expliquez plutôt ce que les lambdas de Ruby peuvent faire, contrairement à ceux de Python. 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 qui sont corrects et ceux que vous connaissez sont 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 des crochets et se termine, et que @ s'appelle self en Python.

MISE À JOUR: Ceci est maintenant un wiki de communauté, nous pouvons donc 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. Dans Python, vous n'avez aucune 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 est dans ce cas la classe, et ce code afficherait "Kaka". Il n'y a aucun moyen d'imprimer le nom de la classe ou d'accéder d'une autre manière à la classe à partir du corps de définition de classe dans Python (en dehors des définitions de méthodes).

Toutes les classes sont mutables en Ruby

Cela vous permet de développer des extensions pour les classes principales. Voici un exemple d'extension 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 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 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 expressions rationnelles 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 utilisant des fichiers texte ou agissant comme un code collant pour d'autres programmes.

Ruby a des suites de première classe

Merci à la déclaration callcc. Dans Python, vous pouvez créer des suites à l'aide de diverses techniques, mais le support ne comprend aucun support.

Ruby a des blocs

Avec l'instruction "do", vous pouvez créer une fonction anonyme multiligne en Ruby, qui sera transmise en tant qu'argument à 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 s'appelle "rendement", ce qui dans 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 supporte plus facilement la programmation de style fonctionnel (semblable à un tuyau)

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 (utilisés comme les blocs Ruby, comme indiqué ci-dessus)

Python prend en charge les générateurs du 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. Vous pouvez également 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 bloc ci-dessus.

Python dispose d'une gestion flexible de l'espace de noms

En 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, puis 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 fichier __init__.py.

Python a docstrings

Les docstrings sont des chaînes attachées à des modules, des fonctions et des méthodes et pouvant être examinées au moment 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
    """

Les équivalents de Ruby sont similaires aux javadocs et se situent au-dessus de la méthode au lieu de l’être. Ils peuvent être récupérés à l'exécution à partir des fichiers en utilisant la méthode 1.9 de # source_location exemple d'utilisation

Python a plusieurs héritages

Ruby ne le fait pas ("à dessein" - voir le site Web de Ruby, voir comment on fait en Ruby ). Il réutilise le concept de module en tant que type de classes abstraites.

Python a des compréhensions liste/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 objets similaires aux décorateurs peuvent également être créés en Ruby, et on peut également affirmer qu'ils ne sont pas aussi nécessaires qu'en Python.

Différences de syntaxe

Ruby a besoin de "fin" ou "}" pour fermer toutes ses portées, alors que Python utilise uniquement des espaces. Il y a eu des tentatives récentes dans Ruby pour autoriser l'indentation d'espaces uniquement http://github.com/michaeledgar/seamless

264
Lennart Regebro

Vous pouvez avoir du code dans la définition de classe à la fois en Ruby et en Python. Cependant, dans Ruby, vous avez une référence à la classe (self). Dans Python, vous n'avez pas de référence à la classe, car la classe n'est pas encore définie.

Un exemple:

class Kaka
  puts self
end

self est dans ce cas la classe, et ce code afficherait "Kaka". Il n'y a aucun moyen d'imprimer le nom de la classe ou d'accéder d'une autre manière à la classe à partir du corps de définition de classe en Python.

5
Lennart Regebro

Ruby a les concepts de blocs , qui sont essentiellement du sucre syntaxique autour d’une section de code; elles sont un moyen de créer des fermetures et de les transmettre à une autre méthode qui peut ou non utiliser le bloc. Un bloc peut être appelé ultérieurement via une instruction yield.

Par exemple, une simple définition d'une méthode each sur Array pourrait ressembler à ceci:

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

Ensuite, vous pouvez invoquer ceci comme suit:

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

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

34
John Feminella

Exemple Python

Les fonctions sont des variables de première classe en Python. Vous pouvez déclarer une fonction, la transmettre en tant qu'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 moyen de faire cela en Ruby, mais ce ne sont pas des opérations de première classe. Par exemple, vous pouvez encapsuler une fonction avec Proc.new pour la traiter comme une variable, mais 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 encapsulées dans un objet pour pouvoir les faire circuler. l'objet résultant ne peut pas être traité comme une fonction. Les fonctions ne peuvent pas être attribuées de première classe; à la place, une fonction de 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!"    
28
Glenn Maynard

En fin de compte, toutes les réponses seront subjectives à un certain niveau, et les réponses postées jusqu'à présent prouvent quasiment à tout le monde que vous ne pouvez indiquer aucune caractéristique non réalisable 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. La consistance de Ruby est d'une beauté zen. Bien qu'aucun exemple trivial ne puisse expliquer cela complètement, je vais essayer d'en trouver un ici juste pour expliquer ce que je veux dire.

Inverser les mots dans cette chaîne:

sentence = "backwards is sentence This"

Lorsque vous réfléchissez à la manière de procéder, procédez comme suit:

  1. Divisez la phrase en mots
  2. Inverser les mots
  3. Re-rejoindre les mots dans une chaîne

En Ruby, vous feriez ceci:

sentence.split.reverse.join ' '

Exactement lorsque vous y réfléchissez, dans le même ordre, une méthode appelle une autre après l'autre.

En python, cela ressemblerait plus à ceci:

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

Ce n’est pas difficile à comprendre, mais le flux n’est pas tout à fait le même. Le sujet (phrase) est enterré au milieu. Les opérations sont un mélange de fonctions et de méthodes d'objet. Ceci est un exemple trivial, mais on découvre de nombreux exemples différents lorsque l'on travaille et comprend vraiment Ruby, en particulier pour des tâches non triviales.

26
Mark Thomas

Python a une mentalité "nous sommes tous des adultes ici". Ainsi, vous constaterez que Ruby a des choses comme des constantes alors que Python ne le fait pas (bien que les constantes de Ruby ne soulèvent qu'un avertissement). La façon de penser de Python est que si vous voulez faire quelque chose de constant, vous devez mettre les noms de variables en majuscules et non 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
18
Jason Baker

Vous ne pouvez importer que des fonctions spécifiques d'un module en Python. En Ruby, vous importez la liste complète des méthodes. Vous pouvez les "importer" en 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 les deux méthode1 et méthode2 ont été ajoutés à votre espace de noms. Vous ne pouvez pas importer uniquement méthode1. Vous les importez tous les deux ou vous ne les importez pas du tout. Dans Python, vous ne pouvez importer que les méthodes de votre choix. Si cela avait un nom, cela s'appellerait peut-être une importation sélective?

18
Geo

De Ruby site web :

Similitudes Comme avec Python, en Ruby, ...

  • Il y a une invite interactive (appelée irb).
  • Vous pouvez lire les documents sur la ligne de commande (avec la commande ri au lieu de pydoc).
  • Il n'y a pas de terminaison de ligne spéciale (à l'exception de la nouvelle ligne habituelle).
  • Les littéraux de chaîne peuvent s'étendre sur plusieurs lignes, comme les chaînes à trois guillemets de Python.
  • Les crochets sont pour les listes et les crochets pour les dict (appelés, en Ruby, des "hash").
  • Les tableaux fonctionnent de la même manière (en les ajoutant, on crée un tableau long, mais en les composant comme ceci a3 = [ a1, a2 ] vous donne un tableau de tableaux).
  • Les objets sont typés de manière forte et dynamique.
  • 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 de documentation intégrés (Ruby’s s'appelle rdoc).

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

  • Les chaînes sont mutables.
  • Vous pouvez créer des constantes (variables dont vous ne souhaitez pas modifier la valeur).
  • Certaines conventions de cas sont appliquées (par exemple, les noms de classe commencent par une lettre majuscule, les variables commencent par une lettre minuscule).
  • Il n’ya 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 les résultats d'expressions Ruby directement dans d'autres chaînes sans avoir à ajouter de chaînes "+" "+" ensemble "). Les chaînes entre guillemets 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, ce sont tous des appels de méthode.
  • Les parenthèses pour les appels de méthode sont généralement facultatives.
  • Il est public, privé et protégé pour imposer l’accès, au lieu de _voluntary_ underscore __convention__ de Python.
  • "Mixin" 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 n'empêche pas la modification des éléments intégrés - Ruby ne le fait pas.
  • Vous avez true et false au lieu de True et False (et nil au lieu de None).
  • Lorsqu’on teste la vérité, seules les valeurs fausses et nulles donnent une valeur fausse. Tout le reste est vrai (y compris 0, 0.0, "" et []).
  • C’est elsif au lieu d’Elif.
  • Il faut au lieu d’importer. Sinon, l'utilisation est la même.
  • Les commentaires de style habituel sur les lignes ci-dessus (au lieu de docstrings en dessous) sont utilisés pour générer des documents.
  • Il existe un certain nombre de raccourcis qui, même s'ils vous donnent plus de choses à retenir, vous apprenez rapidement. Ils ont tendance à rendre Ruby amusant et très productif.
16
kruczkowski

Je ne pense pas que "Ruby a X et Python pas, alors que Python a Y et Ruby pas" est le moyen le plus utile de regarder à cela. Ce sont des langues assez similaires, avec de nombreuses capacités partagées.

Dans une large mesure, la différence réside dans l'élégance et la lisibilité du langage. Pour utiliser un exemple que vous avez évoqué, les deux ont théoriquement des lambdas, mais les programmeurs Python ont tendance à les éviter, et les constructions qui les utilisent ne semblent pas aussi lisibles ni aussi idiomatiques que Ruby. Ainsi, en Python, un bon programmeur voudra choisir un moyen différent de résoudre le problème par rapport à Ruby, simplement parce que c'est en fait est le meilleur moyen de le faire.

12
Chuck

Ce que Ruby a sur Python, ce sont ses capacités en langage de script. Dans ce contexte, langage de script signifie qu’il doit être utilisé pour le "code collant" dans les scripts Shell et la manipulation de texte en général.

Celles-ci sont principalement partagées 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 épressive, il convient parfaitement à ce type de tâches.

Pour moi, le langage Python est plutôt un langage d’affaires à typage dynamique très facile à apprendre et dont la syntaxe est soignée. Pas aussi "cool" que Ruby mais soigné. Ce que Python a sur Ruby est pour moi le grand nombre de liaisons pour les autres bibliothèques. Liaisons à Qt et aux autres bibliothèques de l’interface graphique, nombreuses bibliothèques de support de jeux et et et. Ruby a beaucoup moins. Alors que les liaisons beaucoup utilisées, par exemple Les bases de données sont de bonne qualité. J’ai trouvé que les librairies de niche étaient mieux prises en charge dans Python même si, pour la même bibliothèque, il existe également une liaison Ruby.

Donc, je dirais que les deux langues ont son utilisation 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.

12
haffax

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

Mais qu'en est-il de ceci:

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

Cela peut être beaucoup plus intéressant qu'une simple comparaison de caractéristiques.

12
Christos Hayward

"Les variables commençant par une majuscule deviennent des constantes et ne peuvent pas être modifiées"

Faux. Ils peuvent.

Vous ne recevez un avertissement que si vous le faites.

11
mark

Python a une syntaxe intégrée explicite pour les compréhensions de liste et les générateurs, alors que dans Ruby, vous utiliseriez des blocs de carte et de code.

Comparer

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

à

res = (1..10).map{ |x| x*x }
11
Dario

Copier/coller sans vergogne de: Alex Martelli réponse sur " Quoi de mieux avec Ruby que Python "thread à partir de comp.lang.python liste de diffusion.

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

"Brandon J. Van Every" a écrit:

Quoi de mieux sur Ruby que 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 ceci à Ruby personnes, plutôt qu'à Python personnes?

Peut-être, ou pas, en fonction de l'objectif de votre projet - par exemple, si votre objectif inclut une "étude sociologique" de la communauté Python, le fait de poser des questions à cette communauté est susceptible de fournir des informations plus révélatrices sur ça, que de les mettre ailleurs :-).

Personnellement, j'en ai profité pour suivre le tutoriel d'une journée de Dave Thomas Ruby lors du dernier OSCON. Au-dessous d'une mince couche de différences de syntaxe, je trouve Ruby et Python incroyablement similaires - si je calculais l'arbre de recouvrement minimal parmi à peu près n'importe quel jeu de langues, je suis presque certain Python et Ruby seraient les deux premières feuilles à fusionner en un noeud intermédiaire :-).

Bien sûr, en Ruby, je me lasse de taper le "fin" idiot à la fin de chaque bloc (plutôt que de le laisser indifférent) - mais je ne peux pas non plus taper le "tout aussi idiot" qui Python nécessite au débutde chaque bloc, donc c'est presque un lavage :-). D'autres différences de syntaxe telles que "@foo" par rapport à "self.foo", ou la signification plus importante de la casse dans Ruby vs Python, sont tout aussi importantes pour moi.

D'autres fondent sans doute leur choix de langages de programmation sur de telles questions et génèrent les débats les plus chauds - mais pour moi, ce n'est qu'un exemple de la loi de Parkinson en action (le montant du débat sur une question est inversement proportionnel à celui de la question importance réelle).

Edit (avant le 19/06/2010 à 11h45): on l’appelle aussi "peindre le bikeshed" (ou, pour faire court, "bikeshedding" ") - la référence est, encore une fois, à Northcote Parkinson, qui a donné" des débats sur la couleur à utiliser pour peindre le bikeshed "comme exemple typique de" débats brûlants sur des sujets triviaux ". (fin de l'édition).

Une différence de syntaxe que je trouve importante et en faveur de Python - mais d'autres personnes penseront sans doute au contraire - est "comment appelez-vous une fonction qui ne prend aucun paramètre". En Python (comme en C), pour appeler une fonction, vous appliquez toujours "l'opérateur d'appel" - les parenthèses de fin juste après l'objet que vous appelez (à l'intérieur de ces parenthèses, passez les arguments que vous passez) dans l'appel - si vous ne transmettez aucun argument, les parenthèses sont vides). Cela laisse la simple mention de anyobject, sans opérateur impliqué, ce qui signifie simplement une référence à l'objet - dans n'importe quel contexte, sans cas particuliers, exceptions, règles ad-hoc, etc. Dans Ruby (comme en Pascal), pour appeler une fonction avec des arguments, vous passez les arguments (normalement entre parenthèses, bien que ce ne soit pas toujours le cas) - MAIS si la fonction ne prend aucun argument, il suffit de mentionner le fonction l'appelle implicitement. Cela peut répondre aux attentes de nombreuses personnes (du moins sans doute de ceux dont la seule expérience en programmation était avec Pascal, ou d’autres langages ayant un "appel implicite" similaire, tel que Visual Basic). Mais pour moi, cela signifie la simple mention d'un objet peut signifier SOIT une référence à l'objet, OR un appel à l'objet, en fonction du type de l'objet - et dans les cas où je ne parviens pas à obtenir une référence à l'objet simplement en le mentionnant, je devrai utiliser une expression explicite "donnez-moi une référence à cela, NE PAS l'appeler!" opérateurs qui ne sont pas nécessaires autrement. Je pense que cela a un impact sur la "première classe" des fonctions (ou méthodes, ou autres objets appelables) et sur la possibilité d'échanger des objets en douceur. Par conséquent, pour moi, cette différence de syntaxe spécifique est une marque noire sérieuse contre Ruby - mais je comprends pourquoi les autres voudraient faire autrement, même si je ne pouvais difficilement être en désaccord avec plus véhément avec eux :-).

Sous la syntaxe, nous entrons dans des différences importantes en sémantique élémentaire - par exemple, les chaînes dans Ruby sont des objets mutables (comme en C++), alors que dans Python, elles ne sont pas mutables ( comme en Java, ou je crois en C #). Encore une fois, les personnes qui jugent principalement par ce qu’elles connaissent déjà peuvent penser que c’est un plus pour Ruby (sauf s’ils connaissent Java ou C #, bien sûr :-) . Moi, je pense que les cordes immuables sont une excellente idée (et je ne suis pas surpris que Java, indépendamment de ce que je pense, ait réinventé cette idée qui était déjà en Python), même si cela ne me dérangerait pas d'avoir un type "tampon de chaîne mutable" (et idéalement avec une facilité d’utilisation supérieure à celle des propres "tampons de chaînes" de Java); et je ne donne pas ce jugement pour des raisons de familiarité - avant d’étudier Java, à part les langages de programmation fonctionnels où tousdata sont immuables, tous les langages que je connaissais avaient des chaînes mutables - pour le moment Lorsque j'ai découvert l'idée de chaîne immuable dans Java (que j'avais bien appris avant d'apprendre Python), cela m'a immédiatement semblé excellent, ce qui correspond très bien à la sémantique de référence d'un langage de programmation de niveau supérieur. (par opposition à la sémantique de valeur qui convient le mieux aux langues plus proches de la machine et plus éloignées des applications, telles que C), avec des chaînes comme type de données de première classe, intégré (et plutôt crucial).

Ruby a certains avantages en sémantique élémentaire - par exemple, la suppression de la distinction extrêmement subtile des "listes contre des nuplets" de Python. Mais la plupart du temps, le score (comme je le garde, avec un gros plus et des distinctions subtiles et intelligentes avec un moins notable) est contre {Ruby (avec par exemple des intervalles fermés et semi-ouverts, avec les notations a. .b et a ... b [tout le monde veut prétendre que c'est évidentqui est qui? -)], c'est idiot - à mon humble avis, bien sûr!). Encore une fois, les personnes qui considèrent que beaucoup de choses similaires mais légèrement différentes sont au cœur d'une langue sont PLUS, plutôt que MOINS, les compteront bien sûr "à l'inverse" de la façon dont je les compte :-).

Ne vous fiez pas à ces comparaisons en pensant que les deux langues sont trèsdifférentes, remarquez. Ils ne sont pas. Mais si on me demande de comparer "capelli d'angelo" à "spaghettini", après avoir souligné que ces deux types de pâtes sont indiscernables pour tout le monde et interchangeables dans n'importe quel plat que vous souhaitez préparer, j'aurais alors inévitablement passer à l'examen microscopique de la différence imperceptible des longueurs et des diamètres, de la manière dont les extrémités des brins sont effilées dans un cas et non dans l'autre, et ainsi de suite - pour tenter d'expliquer pourquoi, personnellement, je préférerais avoir du capelli 'angelo comme les pâtes dans n'importe quel bouillon, mais préférerait les spaghettini comme les pastasciutta avec des sauces appropriées pour des pâtes aussi longues et minces (huile d'olive, ail émincé, poivrons rouges émincés et anchois finement moulus, par exemple - mais si au lieu de les émincer, vous devriez choisir le corps de spaghetti plus solide, plutôt que l’évanescence plus fine des spaghettinis, et vous feriez bien de renoncer aux achovies et d’ajouter du basilic de printemps frais [ou même - - Je suis un hérétique ...! - menthe légère ...] feuilles - au tout dernier moment avant de servir le plat). Oups, désolé, cela montre que je pars en voyage à l'étranger et que je n'ai pas mangé de pâtes depuis un moment, je suppose. Mais l'analogie est encore très bonne! -)

Donc, revenons à Python et à Ruby, nous arrivons aux deux grandes choses (en termes de langage proprement dit - laisser les bibliothèques et d’autres outils auxiliaires importants tels que des outils et des environnements, comment intégrer/étendre chaque langage, etc, etc., pour le moment - ils ne s'appliqueraient de toute façon pas à toutes les implémentations de chaque langage, par exemple Jython vs Classic Python étant deux implémentations du langage Python! ):

  1. Les itérateurs et codeblocs de Ruby par rapport aux itérateurs et générateurs de Python;

  2. La "dynamique" totale et débridée de Ruby, y compris la capacité
    pour "rouvrir" toute classe existante, y compris toutes les classes intégrées, et changer son comportement au moment de l'exécution - vs le vaste mais bornédynamicité de Python modifie le comportement des classes intégrées existantes et de leurs instances.

Personnellement, j’estime que 1 est un lavage (les différences sont si profondes que je pouvais facilement voir des gens haïssant l’un ou l’autre et révérant l’autre, mais, à ma balance personnelle, les avantages et inconvénients presque égaux); et 2 une question cruciale - qui rend Ruby beaucoup plus approprié pour "bricoler", MAIS Python également plus approprié pour une utilisation dans les applications de grande production. C'est drôle, dans un sens, parce que les deux langues sont BEAUCOUP plus dynamiques que la plupart des autres, qu'à la fin, la différence essentielle entre elles et mon POV devrait dépendre de cela - que Ruby "passe à onze" à cet égard (la référence ici est "Spinal Tap", bien sûr). Dans Ruby, ma créativité est sans limite - si je décide que toutes les comparaisons de chaînes doivent devenir insensibles à la casse, I CAN DO DO/! Par exemple, je peux modifier dynamiquement la classe de chaînes intégrée de sorte que a = "Hello World" b = "hello world" si un == b print "égal!\N" sinon print "différent!\N" end WILL imprimera " égal". En python, il n'y a AUCUN moyen de le faire. Pour les besoins de la métaprogrammation, de la mise en œuvre de cadres expérimentaux, etc., cette étonnante capacité dynamique de Ruby est extrêmementattrayante. MAIS - si nous parlons d’applications volumineuses, développées par de nombreuses personnes et maintenues par d’autres encore, comprenant toutes sortes de bibliothèques de sources diverses et devant être mises en production sur des sites clients ... eh bien, je ne veux pas une langue qui est assez dynamique, merci beaucoup. Je déteste l'idée même d'une bibliothèque brisant sans le vouloir d'autres bibliothèques sans lien qui s'appuient sur des chaînes différentes - c'est le genre de "canal" profond et profondément caché, entre des morceaux de code qui sont séparés et DEVRAIENT être séparés, ce qui signifie la mort dans programmation à grande échelle. En laissant n'importe quel module affecter le comportement de n'importe quel autre "secrètement", la possibilité de muter la sémantique des types intégrés n'est qu'une mauvaise idée pour la programmation d'applications de production, tout comme c'est cool pour le bricolage.

Si je devais utiliser Ruby pour une application de cette taille, j'essaierais de m'appuyer sur des restrictions de style de codage, sur de nombreux tests (à réexécuter à chaque fois que TOUT change, même ce qui devrait être totalement indépendant ... ), etc., pour interdire l’utilisation de cette fonctionnalité de langage. Mais à mon avis, il est préférable de ne pas disposer de la fonctionnalité en premier lieu, tout comme Python constituerait un langage encore meilleur pour la programmation d'applications si un certain nombre de fonctions intégrées pouvaient être "clouées". ", donc je savais que, par exemple, len (" ciao ") était égal à 4 (plutôt que de devoir se préoccuper de manière subliminale de savoir si quelqu'un avait modifié la liaison du nom" len "dans les commandes intégrées module ...). J'espère que finalement Python "cloue" ses fonctions intégrées.

Mais le problème est mineur, car la recomposition des build-ins est une pratique obsolète ainsi qu’une pratique rare en Python. En Ruby, cela me semble majeur - tout comme les installations trop puissantesmacro d'autres langues (telles que, par exemple, Dylan) présentent des risques similaires à mon avis (j'espère que Python n’obtienne jamais un système macro aussi puissant, peu importe l’attrait de "laisser les gens définir leur propre petit langage propre à un domaine intégré dans le langage lui-même" - cela nuirait à la merveilleuse utilité de Python pour programmation d’applications, en présentant une "nuisance attrayante" au potentiel bricoleur qui se cache dans le cœur de chaque programmeur ...).

Alex

11
OscarRyz

Un peu plus du côté des infrastructures:

  • Python a une bien meilleure intégration avec C++ (via des choses comme Boost.Python , SIP , et Py ++ ) que Ruby, où les options semblent soit écrire directement sur l'API interprète Ruby (ce que vous pouvez faire avec Python également, bien sûr, mais dans les deux cas, il s'agit d'un niveau bas, fastidieux et sujet aux erreurs ) ou utilisez SWIG (qui, bien que cela fonctionne et qu’il est vraiment génial si vous voulez supporter de nombreuses langues, n’est pas aussi agréable que Boost.Python ou SIP si vous cherchez spécifiquement à lier C++).

  • Python a un certain nombre d'environnements d'applications Web (Django, Pylons/Turbogears, web.py, probablement au moins une demi-douzaine d'autres), alors que Ruby (effectivement) en a un: Rails. (D'autres Ruby structures web existent, mais semblent avoir du mal à gagner du terrain face à Rails). Cet aspect est-il bon ou mauvais? Difficile à dire et probablement assez subjectif; Je peux facilement imaginer des arguments indiquant que la situation Python est meilleure et que la situation Ruby est meilleure.

  • Culturellement, les communautés Python et Ruby semblent quelque peu différentes, mais je ne peux que le dire, car je n'ai pas beaucoup d'expérience en interaction avec la communauté Ruby . J'ajoute cela principalement dans l'espoir que quelqu'un qui a beaucoup d'expérience avec les deux puisse amplifier (ou rejeter) cette affirmation.

11
Jack Lloyd

Quelques autres de:

http://www.Ruby-lang.org/en/documentation/Ruby-from-other-languages/to-Ruby-from-python/

(Si j'ai mal interprété quelque chose ou si l'un d'entre eux a changé côté Ruby depuis la mise à jour de cette page, quelqu'un se sent libre de le modifier ...)

Les chaînes sont modifiables en Ruby, pas en Python (où de nouvelles chaînes sont créées par "modifications").

Ruby a des conventions de cas appliquées, pas Python.

Python a à la fois des listes et des tuples (listes immuables). Ruby a des tableaux correspondant aux listes Python, mais aucune variante immuable de ceux-ci.

En Python, vous pouvez accéder directement aux attributs d'objet. En Ruby, c'est toujours via des méthodes.

En Ruby, les parenthèses pour les appels de méthodes sont généralement facultatives, mais pas en Python.

Ruby dispose de fonctions publiques, privées et protégées pour imposer l’accès, au lieu de la convention de Python consistant à utiliser des traits de soulignement et des noms malins.

Python a plusieurs héritages. Ruby a des "mixins".

Et un autre lien très pertinent:

http://c2.com/cgi/wiki?PythonVsRuby

Qui, en particulier, renvoie à un autre bon article d’Alex Martelli , qui a également publié beaucoup d’excellentes choses ici sur SO:

http://groups.google.com/group/comp.lang.python/msg/028422d70751228

9
Anon

Je ne suis pas sûr de cela, je l'ajoute donc d'abord comme réponse.

Python traite les méthodes non liées comme des fonctions

Cela signifie que vous pouvez appeler une méthode comme theobject.themethod() ou par TheClass.themethod(anobject).

Edit: Bien que la différence entre les méthodes et les fonctions soit faible en Python et inexistante en Python 3, elle n’existe pas non plus en Ruby, simplement parce que Ruby n’a pas les fonctions. Lorsque vous définissez des fonctions, vous définissez en fait des méthodes sur Object.

Mais vous ne pouvez toujours pas prendre la méthode d'une classe et l'appeler en tant que fonction, vous devrez la relier à l'objet sur lequel vous voulez faire appel, ce qui est beaucoup plus obstiné.

8
Lennart Regebro

Je voudrais mentionner l'API de descripteur Python qui permet de personnaliser la "communication" entre objets. Il convient également de noter qu’en Python, il est libre d’implémenter un protocole alternatif en remplaçant la valeur par défaut donnée par l’implémentation par défaut de la méthode __getattribute__. Permettez-moi de donner plus de détails sur ce qui précède. Les descripteurs sont des classes régulières avec les méthodes __get__, __set__ et/ou __delete__. Lorsque l'interprète rencontre quelque chose comme anObj.anAttr, les opérations suivantes sont effectuées:

  • __getattribute__ la méthode de anObj est invoquée
  • __getattribute__ récupère un objet Atttr de la classe dict
  • il vérifie si un objet abAttr a __get__, __set__ ou __delete__ objets appelables
  • le contexte (c'est-à-dire, l'objet appelant ou la classe, et la valeur, au lieu de cette dernière, si nous avons setter) est passé à l'objet appelable
  • le résultat est retourné.

Comme il a été mentionné, il s’agit du comportement par défaut. On est libre de changer le protocole en ré-implémentant __getattribute__.

Cette technique est beaucoup plus puissante que les décorateurs.

7
Giorgi

A ce stade, Python a toujours un meilleur support unicode

6
John La Rooy

Ruby a intégré le support de continuation en utilisant callcc.

Par conséquent, vous pouvez implémenter des choses cool comme le amb-operator

6
Dario

Ruby a une boucle ligne par ligne sur les fichiers d'entrée (l'indicateur '-n') à partir de la ligne de commande afin qu'il puisse être utilisé comme AWK. Ce Ruby one-liner:

Ruby -ne 'END {puts $.}'

comptera des lignes comme AWK one-liner:

awk 'END{print NR}'

Ruby obtient cette fonction via Perl, ce qui lui a valu d’être utilisé par AWK pour que les administrateurs système s’associent à Perl sans avoir à changer leur façon de faire.

5
Pinochle

Mon python est rouillé, donc certains d'entre eux sont peut-être en python et je ne me souviens tout simplement pas/je n'ai jamais appris, mais voici les quelques premiers auxquels j'ai pensé:

Espace blanc

Ruby gère les espaces complètement différents. Pour commencer, vous n'avez pas besoin d'indenter quoi que ce soit (ce qui signifie que peu importe si vous utilisez 4 espaces ou 1 tabulation). Il assure également la continuité de la ligne intelligente. Par conséquent, les éléments suivants sont valides:

def foo(bar,
        cow)

En gros, si vous vous retrouvez avec un opérateur, cela détermine ce qui se passe.

Mixins

Ruby a des mixins qui peuvent étendre des instances au lieu de classes complètes:

module Humor
  def tickle
    "hee, hee!"
  end
end
a = "Grouchy"
a.extend Humor
a.tickle    »   "hee, hee!"

Enums

Je ne suis pas sûr que ce soit la même chose que les générateurs, mais à partir de Ruby 1.9 Ruby en énum,

>> enum = (1..4).to_enum
=> #<Enumerator:0x1344a8>

Référence: http://blog.nuclearsquid.com/writings/Ruby-1-9- what-s-new- what-s-changed

"Arguments de mots clés"

Les deux éléments énumérés ici sont pris en charge dans Ruby, bien que vous ne puissiez pas ignorer les valeurs par défaut de cette manière. Vous pouvez soit aller dans l'ordre

def foo(a, b=2, c=3)
  puts "#{a}, #{b}, #{c}"
end
foo(1,3)   >> 1, 3, 3
foo(1,c=5) >> 1, 5, 3
c          >> 5

Notez que c = 5 attribue effectivement la valeur 5 à la variable c dans l'étendue de l'appel et définit le paramètre b la valeur 5.

ou vous pouvez le faire avec des hachages, qui abordent le deuxième problème

def foo(a, others)
  others[:b] = 2 unless others.include?(:b)
  others[:c] = 3 unless others.include?(:c)
  puts "#{a}, #{others[:b]}, #{others[:c]}"
end
foo(1,:b=>3) >> 1, 3, 3
foo(1,:c=>5) >> 1, 2, 5

Référence: Le guide du programmeur pragmatique à Ruby

5
Scott Dugas

Ruby a des sigils et des brindilles, Python n'en a pas.

Edit : Et une chose très importante que j'ai oubliée (après tout, la précédente était juste pour flamber un peu :-p):

Python a un compilateur JIT ( Psyco ), un langage de niveau inférieur permettant d’écrire du code plus rapide ( Pyrex ) et la possibilité d’ajouter du code C++ intégré ( Weave ).

5
fortran

Python a docstrings et Ruby non ... Ou si ce n'est pas le cas, ils ne sont pas accessibles aussi facilement qu'en python.

Ps. Si je me trompe, jolie s'il vous plaît, laissez un exemple? J'ai une solution de contournement que je pourrais facilement combiner en classes, mais je voudrais avoir docstring un peu d'une fonctionnalité de "manière native".

5
rasjani

La syntaxe n'est pas une chose mineure, elle a un impact direct sur notre façon de penser. Cela a également un effet direct sur les règles que nous créons pour les systèmes que nous utilisons. À titre d'exemple, nous avons l'ordre des opérations en raison de la façon dont nous écrivons des équations ou des phrases mathématiques. La notation standard pour les mathématiques permet aux gens de la lire de plusieurs manières et d'arriver à des réponses différentes en donnant la même équation. Si nous avions utilisé la notation préfixe ou postfixée, nous aurions créé des règles pour distinguer les nombres à manipuler plutôt que de simplement définir des règles pour l’ordre dans lequel les valeurs doivent être calculées.

La notation standard indique clairement les nombres dont nous parlons tout en rendant l'ordre dans lequel les calculer est ambigu. Les notations préfixes et postfixes déterminent l'ordre dans lequel calculer, tout en rendant les chiffres ambigus. Python aurait déjà des lambdas multilignes si ce n'était des difficultés causées par les espaces syntaxiques. (Il existe des propositions pour retirer ce genre de chose sans nécessairement ajouter des délimiteurs de bloc explicites.)

Je trouve qu'il est plus facile d'écrire des conditions dans lesquelles je veux que quelque chose se produise si une condition est false beaucoup plus facile d'écrire avec l'instruction less si dans Ruby que l'équivalent sémantique "if-not" construction en Ruby ou dans d’autres langues, par exemple. Si la plupart des langues que les gens utilisent aujourd'hui ont le même pouvoir, comment la syntaxe de chaque langue peut-elle être considérée comme une chose triviale? Après des caractéristiques spécifiques telles que les blocs et les mécanismes d'héritage, etc., la syntaxe est la partie la plus importante d'un langage, rarement superficielle.

Ce qui est superficiel, ce sont les qualités esthétiques de la beauté que nous attribuons à la syntaxe. L'esthétique n'a rien à voir avec le fonctionnement de notre cognition, mais avec la syntaxe.

4
shadow skill

Surpris de ne rien voir mentionnant le mécanisme de "méthode manquante" de Ruby. Je donnerais des exemples de méthodes find_by _... dans Rails, comme exemple de la puissance de cette fonctionnalité de langage. Mon hypothèse est que quelque chose de similaire pourrait être implémenté en Python, mais à ma connaissance, il n'y en a pas nativement.

3
MikeIsGo

python a nommé des arguments optionnels

def func(a, b=2, c=3):
    print a, b, c

>>> func(1)
1 2 3
>>> func(1, c=4)
1 2 4

Autant que je sache, Ruby n'a positionné que des arguments, car b = 2 dans la déclaration de fonction est une affectation qui est toujours ajoutée.

3
Batiste Bieler

Une autre différence dans les lambdas entre Python et Ruby est démontrée par le problème Accumulator Generator de Paul Graham. Réimprimé ici:

Ecrivez une fonction foo qui prend un nombre n et renvoie une fonction qui prend un nombre i et n incrémenté de i. Remarque: (a) c'est un nombre, pas un entier, (b) qui est incrémenté de, pas plus.

En Ruby, vous pouvez faire ceci:

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

En Python, vous créez un objet pour conserver l'état de n:

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

Certaines personnes pourraient préférer l'approche explicite Python comme étant plus claire sur le plan conceptuel, même si elle est un peu plus détaillée. Vous stockez l'état comme vous le faites pour toute autre chose. Vous avez juste besoin de vous envelopper de l'idée d'objets appelables. Mais quelle que soit l’approche que l’on préfère esthétiquement, cela montre un aspect sous lequel Ruby lambdas sont des constructions plus puissantes que celles de Python.

3
dormsbee
2
Dustin Getz

Ruby a intégré la documentation:

 =begin

 You could use rdoc to generate man pages from this documentation

 =end
2
ko-dos

En Ruby, lorsque vous importez un fichier avec require, toutes les choses définies dans ce fichier se retrouveront dans votre espace de noms global.

Avec Cargo , vous pouvez " demander 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 = importation ("foo-1.0.0") 
 >> Foo2 = importation ("foo-2.0.0") 
 >> Foo1 :: VERSION 
 => "1.0.0" 
 >> Foo2 :: VERSION 
 => "2.0.0" 
2
Jonas Elfström

J'aime les différences fondamentales dans le fonctionnement des invocations de méthode Ruby et Python.

Les méthodes Ruby sont appelées via un formulaire "message en passant" et n'ont pas besoin d'être explicitement des fonctions de première classe (il existe des façons de méthodes d'ascenseur en "objets" fonctionnels "appropriés) - dans cet aspect Ruby est similaire à Smalltalk.

Python fonctionne beaucoup plus comme JavaScript (ou même Perl) où les méthodes sont des fonctions invoquées directement (il y a aussi des informations de contexte stockées, mais ...)

Bien que cela puisse sembler un détail "mineur", il ne s'agit en réalité que de la surface différente du Ruby et du Python dessins sont. (Par contre, ils sont aussi très semblables :-)

Une différence pratique est le concept de method_missing in Ruby (qui, pour le meilleur ou pour le pire, semble être utilisé dans certains cadres populaires). En Python, on peut (au moins partiellement) émuler le comportement en utilisant __getattr __/__ getattribute__, bien que de manière non idiomatique.

1
user166390

En savoir plus sur les blocs de Ruby

Il a été suggéré que les blocs de Ruby puissent être "substitués" par les gestionnaires de contexte de Python. En fait, les blocs permettent plus que ne peuvent en faire les gestionnaires de contexte de Python.

La méthode de réception d'un bloc pourrait exécuter le bloc dans le contexte d'un objet, permettant ainsi au bloc d'appeler des méthodes autrement inaccessibles. Les générateurs de Python ne peuvent pas le faire non plus.

Un exemple simple peut aider:

class Proxy
   attr_accesor :target

   def method &block
      # Ruby 1.9 or in Rails 2.3
      target.instance_exec &block  
   end
end

class C
   private
   def hello
     puts "hello"
   end
end

p = Proxy.new
c = C.new
p.target = c
p.method { hello }

Dans cet exemple, l'appel de méthode dans le bloc { hello } a sa véritable signification dans le contexte de l'objet cible c.

Cet exemple est uniquement à des fins d'illustration. Un code de travail réel qui utilise ce type d'exécution dans le contexte d'un autre objet n'est pas rare. L'outil de surveillance Godm, par exemple, l'utilise.

0
manu

L'exemple de la portée lexicale imbriquée donné par quelqu'un donne plusieurs avantages.

  1. Globals "plus sûrs"
  2. C'est une méthode pour intégrer les DSL dans votre programme.

Je pense que c'est un très bon exemple des différences entre les deux langues. Ruby est simplement plus flexible. Python peut être flexible, mais vous devez souvent faire des contorsions extrêmes pour y arriver, ce qui ne vaut pas la peine.

Désolé de ne pas avoir posté sous la réponse originale, je suppose que je n’ai pas le privilège de le faire.

0
David