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

263

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 ''.startswithmé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, anotherou vous pouvez simplement import themoduleaccé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__.pyfichier.

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

Lennart Regebro
la source
2
En ce qui concerne l'héritage multiple, dire simplement «Ruby ne fait pas» est faux. Je ne peux penser à rien de ce que vous pouvez faire en Python avec héritage multiple que vous ne pouvez pas faire en ruby ​​avec des modules / "héritage mixin". (On peut même soutenir que l'inclusion de modules simplement est un héritage multiple.)
Logan Capaldo
2
Que vous puissiez faire la même chose d'une autre manière est un argument qui ne tient pas. Vous pouvez tout faire ici d'une autre manière. Et puisque les modules ne sont pas des classes, ce n'est pas un héritage multiple. Vous êtes invités à fournir des exemples de code sur la façon dont cela se fait dans l'héritage multiple Pythons vs avec les modules Rubys.
Lennart Regebro
3
Les modules ne sont pas des classes mais les classes sont des modules. % ruby ​​-e 'p Class <Module' true
Logan Capaldo
8
-1 Malheureusement, cette question manque son objectif et la plupart des différences supposées ne sont pas du tout des différences et la désinformation abonde!
biais
2
Les modules inclus sont en fait des héritages multiples, non seulement dans le concept mais dans l'implémentation réelle dans l'interpréteur Ruby. Lorsqu'un module Ruby est inclus, il est injecté dans la chaîne d'héritage exactement de la même manière que les superclasses. La résolution de la méthode est la même. Dans Ruby, plusieurs modules incluent l'héritage multiple. Quiconque veut contester cela comme sémantiquement «pas la même chose» que l'héritage multiple est simplement pédant. Quel est l'intérêt de quelque chose qui n'est pas la "même chose" si l'effet est identique et tout aussi facile à obtenir? Une distinction sans différence.
Dave Sims,

Réponses:

34

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é ultérieurement via une yieldinstruction.

Par exemple, une définition simple d'une eachméthode sur Arraypourrait ê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  

Ensuite, 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 de blocs car il manque une partie du sucre syntaxique utile. Cependant, il existe au moins un moyen de l'obtenir de façon ponctuelle. Voir, par exemple, ici .

John Feminella
la source
6
@Lennart: à part votre exemple qui est horrible, il est également faux du point de vue syntaxique.
2
@unbeknow: A, à droite. Mais si cela avait été une fonction au lieu d'une impression, cela aurait fonctionné. En python 3, cela fonctionne: [print (e + 5) for e in [1,2,3,4]] Et quand il s'agit d'horreur, je pense que le code rubis ci-dessus est horrible, donc c'est clairement subjectif et donc pas un partie de cette question. @John Je ne dis pas que c'est équivalent, je dis que la différence avec votre exemple n'est pas évidente. @Bastien, non, mais le fait de pouvoir faire des choses similaires ne signifie pas qu'elles sont identiques. Les différences ici doivent être répertoriées même s'il existe d'autres moyens de le faire.
Lennart Regebro
22
Je suis programmeur Python. Je voudrais voir un exemple de la façon dont les blocs Ruby vous aident à écrire quelque chose de plus concis ou plus beau qu'avec Python car il n'a pas de blocs. Votre exemple pourrait être écrit: pour i dans [1, 2, 3, 4]: print (i + 5). Il n'utilise pas de blocs, mais son concis et beau ainsi que le rubis chaque exemple.
Manuel Ceron
10
@Manuel, les procs sont utiles pour attacher des foncteurs à des structures de données non triviales (arbres, graphiques ...) qui ne peuvent pas être "for-loopées" et nécessitent donc des itérateurs spéciaux transversaux. Les blocs, qui sont des procs anonymes, vous permettent d'implémenter le foncteur en une seule expression (vs définir puis implémenter), ce qui accélère considérablement le processus de codage et clarifie l'intention. Par exemple, si vous créez une structure de données de graphique, vous pouvez définir un «chaque» itérateur, puis mélanger Enumerable qui vous donnerait instantanément accès à des dizaines d'itérateurs (trier, tous?, Tous?, Grep). Maintenant, vous appelez un bloc ...
biais
4
@RommeDeSerieux, car il a besoin d'un nom dans la langue! De plus, c'est un objet fonction, pas une fonction. Regardons les Ruby Docs: "Les objets Proc sont des blocs de code qui ont été liés à un ensemble de variables locales" donc un Proc anonyme n'est que le bloc et ce n'est certainement pas seulement une fonction!
biais
28

Exemple Python

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

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

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

Il s'agit d'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 existe des moyens de faire ces choses dans 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 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 optimale. à 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!"    
58%
la source
8
Vous êtes très confus. Les objets de première classe sont attribués par affectation:, x = yet non par appel self.class.send(:define_method, :func, method(:func2)). Votre "contre-exemple" montre à quel point les fonctions de Ruby ne sont pas de première classe. Si vous n'êtes pas d'accord, n'hésitez pas à poster votre propre réponse; ne collez pas votre confusion dans la mienne.
Glenn Maynard
7
Les choses définies par def ... endin ruby ​​ne sont pas des fonctions. Ce sont des méthodes (comme vous les avez définies, de Kernel). Les méthodes peuvent être non liées (en utilisant la #methodméthode), qui sont alors des objets. La chose la plus proche que ruby ​​a des fonctions sont les Procinstances, qui sont également des objets, et peuvent être transmises ou invoquées. Il a également une syntaxe spéciale pour passer un seul rappel Procà une méthode, comme l'explique John Feminella dans sa réponse .
rampion
4
@Glenn: Je comprends ce que vous dites, mais je chicanerais avec l'affirmation que les fonctions de redéfinition de Ruby - les méthodes sont un concept sémantique distinct. Si vous voulez jouer au jeu de définition, le code le plus impératif est les procédures, pas les fonctions. Je n'essaie pas d'être difficile, c'est juste que je crois que les définitions et l'exactitude sont importantes. Je suis d'accord que manipuler un UnboundMethodpeut être un PITA, tho.
rampion
5
@Glenn: La beauté est dans l'œil du spectateur. Néanmoins, les méthodes sont des objets de première classe en remplissant la définition (dans ce cas, je fais référence à la définition de Wikipedia). Peut-être, vous avez une autre définition de première classe? Ont-ils besoin d'une carte Platinum Frequent Flier pour passer en première classe?
biais
4
@Glenn Consultez la section FAQ SO "D'autres personnes peuvent-elles modifier mes données?!" - c'est un wiki communautaire.
biais
26

En fin de compte, toutes les réponses vont être 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 fonctionnalité qui n'est pas faisable dans l'autre langue d'une manière tout aussi agréable (sinon similaire) , car les deux langues sont très concises et expressives.

J'aime la syntaxe de Python. Cependant, vous devez creuser un peu plus profondément 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 expliquer cela complètement, je vais essayer d'en trouver un ici juste pour expliquer ce que je veux dire.

Inversez les mots de cette chaîne:

sentence = "backwards is sentence This"

Lorsque vous réfléchissez à la façon dont vous le feriez, vous procédez comme suit:

  1. Divisez la phrase en mots
  2. Inverser 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, un appel de méthode après l'autre.

En python, cela ressemblerait plus à ceci:

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

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

Mark Thomas
la source
1
Je suis d'accord. Ruby semble couler naturellement quand je l'écris, donc "zenlike" est un bon terme.
The Tin Man
18

Python a une mentalité "nous sommes tous des adultes ici". Ainsi, vous constaterez que Ruby a des choses comme des constantes alors que Python n'en a pas (bien que les constantes de Ruby ne déclenchent qu'un avertissement). La façon de penser Python est que si vous voulez rendre quelque chose constant, vous devez 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
Jason Baker
la source
19
Ha .. cela me rappelle juste qu'au moins en python 2. *, vous avez pu faire "Vrai, Faux = Faux, Vrai" ... Je crois qu'ils ont correctement corrigé cela en python 3.0 ... c'est quelque chose que vous devriez être empêché de faire.
Tom
11
Personnellement, j'aime les directives strictes imposées par le langage car il rend cohérent tout le code écrit dans ce langage. Cela vous oblige à suivre les directives, et les développeurs qui lisent votre code peuvent dire d'un coup d'œil ce qui est quoi. Bien que la plupart des codeurs Python utilisent le même "style" général, j'ai vu quelques incohérences assez importantes qui ne seraient pas possibles dans Ruby.
Sasha Chedygov
8
@bias - Je ne sais pas pourquoi vous me dévaluez. Cette réponse n'est pas d'accord ou en désaccord avec la façon de faire des choses en python. Ce n'est qu'une déclaration de fait.
Jason Baker
13
@Jason "nous sommes tous des adultes ici" est une déclaration de fait? Je voudrais appeler cela une opinion enroulée autour d'une fonctionnalité, d'où le vote négatif.
biais
7
@bias - Dire "nous sommes tous des adultes ici" n'était pas censé être un léger. C'est une devise Poffon
Evan Porter
18

Vous ne pouvez importer que des fonctions spécifiques à partir d'un module en Python. Dans Ruby, vous importez toute la liste des méthodes. Vous pouvez les "désimporter" dans Ruby, mais ce n'est pas de cela qu'il s'agit.

ÉDITER:

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 méthodes method1 et method2 ont été ajoutées à votre espace de noms. Vous ne pouvez pas importer uniquement method1 . Soit vous les importez tous les deux, soit vous ne les importez pas du tout. En Python, vous ne pouvez importer que les méthodes de votre choix. Si cela avait un nom, ce serait peut-être appelé importation sélective?

Tempus
la source
2
Oh, c'est vrai! Python aime les espaces de noms. N'est-ce pas le cas chez Ruby? Tu n'es pas import bla; bla.foo()en Ruby?
Lennart Regebro
2
Vous ne pouvez importer que la fonction a, pas toutes les fonctions à l'intérieur. Si, par exemple, vous incluez un module Ruby qui déclare 3 fonctions non statiques, vous les obtenez toutes incluses dans votre espace de noms. En python, vous devez écrire depuis l'importation de module *.
Geo
6
Cela ne conduit-il pas à un encombrement important de l'espace de noms?
Lennart Regebro
1
Je pense que oui. C'est ce que je déteste à propos des modules Ruby.
Geo
8
Ruby n'a pas vraiment de système de modules au même sens que python. nécessite des travaux essentiellement sous forme d'inclusion textuelle avec quelques vérifications de l'inclusion en dupilicate. Vous pouvez (ab) utiliser des modules comme espaces de noms mais moduleest en fait un peu inapproprié. Les modules sont essentiellement les classes sans la new, allocateméthodes. Ils fonctionnent mieux comme moyen de partager du code par classe / objet, pas comme mécanisme de partitionnement de bibliothèques ou pour partager du code entre programmes.
Logan Capaldo
16

Du site Web de Ruby :

Similitudes Comme avec Python, en Ruby, ...

  • Il y a une invite interactive (appelée irb).
  • Vous pouvez lire des 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 (sauf la nouvelle ligne habituelle).
  • Les littéraux de chaîne peuvent s'étendre sur plusieurs lignes, comme les chaînes entre guillemets triples de Python.
  • Les crochets sont pour les listes, et les accolades sont pour les dits (qui, en Ruby, sont appelés «hachages»).
  • Les tableaux fonctionnent de la même manière (en les ajoutant, a3 = [ a1, a2 ]vous obtenez un long tableau, mais en les composant comme ceci, vous obtenez 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 de la même manière.
  • Vous avez des outils de documentation intégrés (Ruby s'appelle rdoc).

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

  • Les cordes sont mutables.
  • Vous pouvez créer des constantes (variables dont vous n'avez pas l'intention de changer la valeur).
  • Il existe certaines conventions de casse appliquées (par exemple, 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 modifiable.
  • Les chaînes entre guillemets permettent les séquences d'échappement (comme \ t) et une syntaxe spéciale de «substitution d'expression» (qui vous permet d'insérer les résultats des expressions Ruby directement dans d'autres chaînes sans avoir à «ajouter» + «chaînes» + «ensemble») . Les chaînes entre guillemets simples sont comme les r "chaînes brutes" de Python.
  • Il n'y a pas de classes «nouveau style» et «ancien style». Un seul type.
  • 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 y a public, privé et protégé pour imposer l'accès, au lieu de Python _voluntary_ underscore __convention__.
  • Les «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 intégrés - Ruby ne le fait pas.
  • Vous avez vrai et faux au lieu de vrai et faux (et nul au lieu de aucun).
  • Lorsqu'ils sont testés pour la vérité, seuls false et nil donnent une valeur fausse. Tout le reste est vrai (y compris 0, 0,0, "" et []).
  • C'est elsif au lieu d'elif.
  • C'est exiger au lieu d'importer. Sinon, l'utilisation est la même.
  • Les commentaires de style habituel sur la (les) ligne (s) au-dessus des éléments (au lieu des docstrings en dessous) sont utilisés pour générer des documents.
  • Il existe 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.
kruczkowski
la source
2
"Il faut au lieu d'importer. Sinon, l'utilisation est la même." Semble être complètement inexact.
Glenjamin le
Il existe également des ensembles dans Ruby que les gens utilisent rarement, mais ils sont intégrés. Je peux donc dire, stuff_in_backpack = Set.new; stuff_in_backpack << "ordinateur"; stuff_in_backpack << "chaussures"; # et l'ensemble contiendra toutes les valeurs sans garantir l'ordre.
zachaysan
12

Ce que Ruby a sur Python, ce sont ses capacités de langage de script. Langage de script dans ce contexte signifiant à utiliser pour le "code de colle" 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 épique, il est parfait pour ce genre de tâches.

Pour moi, Python est plus un langage commercial typé dynamiquement qui est très facile à apprendre et a 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 d'autres bibliothèques. Liaisons à Qt et à d'autres bibliothèques GUI, de nombreuses bibliothèques de support de jeux et et et. Ruby en a beaucoup moins. Bien que les liaisons très utilisées, par exemple aux bases de données, soient de bonne qualité, j'ai trouvé que les bibliothèques de niche étaient mieux prises en charge en Python même si pour la même bibliothèque, il existe également une liaison Ruby.

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

haffax
la source
1
Question de quelqu'un qui ne connaît pas encore Ruby: Qu'entendez-vous par "$ -Variables"? Voulez-vous dire des variables globales? Si c'est le cas, en Python, une variable définie dans un module en dehors d'une classe ou d'une fonction est globale. Sinon - quelle est la distinction?
Anon
1
Anon: si vous déclarez une variable $ n'importe où dans le code, elle est globale à cause du préfixe. Ainsi, peu importe où il est défini, il est toujours global et toujours connu comme tel.
Robert K
8
Pas exactement, en fait je voulais dire des variables prédéfinies comme $ _, $ 1 etc. Celles-ci sont automatiquement remplies de valeurs par ruby ​​lui-même. $ _ est la dernière ligne lue. $ 1, $ 2, etc. sont les correspondances d'expressions régulières de la dernière correspondance. Voir ici pour une liste complète: zenspider.com/Languages/Ruby/QuickRef.html#17 Il s'agit essentiellement d'un hack pour les scripts compacts. Vous pouvez également obtenir toutes les informations via des appels API, mais en utilisant $ variables, il est plus concis. Ce type de variables ne convient tout simplement pas au style de Python, elles les ont délibérément laissées de côté.
haffax
Merci pour ce lien zenspider - cherchait quelque chose comme ça pour une sensation rapide (non tutorielle) pour Ruby.
Anon
12

Je ne pense pas que "Ruby a X et Python pas, alors que Python a Y et Ruby n'a pas" est la façon la plus utile de le voir. Ce sont des langues assez similaires, avec de nombreuses capacités partagées.

Dans une large mesure, la différence réside dans ce que la langue rend élégant et lisible. Pour utiliser un exemple que vous avez cité, les deux ont théoriquement des lambdas, mais les programmeurs Python ont tendance à les éviter, et les constructions faites en les utilisant ne semblent pas aussi lisibles ou idiomatiques que dans Ruby. Donc, en Python, un bon programmeur voudra prendre une voie différente pour résoudre le problème qu'il ne le ferait en Ruby, simplement parce que c'est en fait la meilleure façon de le faire.

Mandrin
la source
5
Je suis d'accord que les lambdas ont une portée limitée et ne sont pas utiles dans de nombreux cas. Cependant, je ne pense pas qu'il soit juste de dire que les programmeurs Python les évitent comme la peste.
Jason Baker
1
Je suis d'accord que les lambdas sont souvent utilisés avec Python - comme avec map, filter, Reduce. La grande différence semble être que les lambdas Python sont limités aux expressions alors que les blocs Ruby peuvent être multilignes et impliquer des instructions. Mon impression générale de ce que j'ai lu sur Ruby est que cette fonctionnalité incite en particulier les Rubyistes à adopter l'approche DSL, tandis que les Pythonistas sont plus susceptibles de créer des API. Mes informations sur Ruby sont cependant très superficielles.
Anon
2
@Lennart: Les blocs multilignes sont utilisés tout le temps dans Ruby - plus souvent que je ne vois de lambdas utilisés dans le code Python idiomatique, en fait. Pour un exemple courant, voir info.michael-simons.eu/2007/08/06/rails-respond_to-method .
Chuck
1
@Lennart: Non, il n'utilise pas de rendement. (Le rendement de Ruby est complètement différent de celui de Python de toute façon - il ne retourne pas de générateur.) Ce ne serait pas significatif d'écrire for format in respond_to(). La respond_tométhode ne renvoie rien de significatif - elle répond simplement à la requête HTTP actuelle. L' doentrée respond_to doest le début d'un bloc. Dans ce bloc, nous parlons à un objet temporaire (étiqueté formatdans cet exemple) qui implémente un DSL très basique pour répondre à une requête HTTP.
Chuck
3
Pouvez-vous mélanger Enumerable contre un générateur et obtenir instantanément 30 nouveaux et merveilleux itérateurs? Vous devez regarder la langue dans son ensemble avant de comprendre pourquoi les blocs / Procs sont excellents.
biais
12

Je voudrais suggérer une variante de la question d'origine, "Qu'est-ce que Ruby a que Python n'a pas, 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 en 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:

Que peut-on faire gracieusement 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 qu'une simple comparaison de fonctionnalités.

Christos Hayward
la source
un commentaire au mieux. toujours mon +1
nawfal
11

Python a une syntaxe intégrée explicite pour les listes de compréhension 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 }
Dario
la source
comment les compréhensions de liste ne sont pas un simple Python ? et il y a aussi une fonction de carte en Python.
SilentGhost
Mais il n'y a pas de syntaxe de compréhension de liste dans Ruby
Dario
Python: res = map (lambda x: x * x, range (1,10))
GogaRieger
Python:res=map(2 .__rpow__, range(1,10))
John La Rooy
11

"Les variables qui commencent 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.

marque
la source
2
Si une langue vous avertit d'une opération, je pense que vous pouvez très bien considérer l'opération comme "impossible". Tout le reste est de la folie.
porgarmingduod
11

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 être soit écrites directement sur l'API de l'interpréteur Ruby (ce que vous pouvez également faire avec Python, bien sûr, mais dans les deux cas, le faire est de bas niveau, fastidieux et sujet aux erreurs) ou utilisez SWIG (qui, bien que cela fonctionne et est certainement génial si vous souhaitez prendre en charge 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), tandis que Ruby en a un: Rails. (D'autres frameworks Web Ruby existent, mais semblent avoir du mal à obtenir beaucoup de traction contre Rails). Cet aspect est-il bon ou mauvais? Difficile à dire et probablement assez subjectif; Je peux facilement imaginer des arguments selon lesquels 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 faire allusion à cela 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 déclaration.

Jack Lloyd
la source
7
Votre deuxième point est au mieux mal informé. Vous devriez commencer par regarder Rack et Sinatra
Max Ogden
6
Je note explicitement que d'autres piles Rails existent; Je pense juste que personne ne les utilise réellement. Vérifier Sinatra et Rack n'a pas changé exactement cette impression. Pensez-vous vraiment que, disons, Sinatra (94 questions SO au total), ou Camping (2 questions SO au total), ou l'une des autres, a réellement une véritable base d'utilisateurs / communauté? La plupart d'entre eux n'ont même pas d'utilisateurs réels, pour autant que je sache. Comparez avec Django (4K +) ou Rails (7K +), ou même web.py d'ailleurs.
Jack Lloyd
1
Sinatra est en fait plutôt populaire pour différentes tâches légères en raison de sa DSL. C'est juste moins utilisé parce que le MVC de Rail offre plus. Rails est en fait construit sur Rack - C'est ce qui rend Phusion Passenger possible.
alternative
11

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

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

"Brandon J. Van Every" a écrit:

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

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

Peut ou non, selon ses objectifs - par exemple, si ses objectifs incluent 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 placer ailleurs :-).

Personnellement, j'ai volontiers profité de l'occasion pour suivre le tutoriel Ruby d'une journée de Dave Thomas au dernier OSCON. Ci-dessous un mince placage de différences de syntaxe, je trouve Ruby et Python incroyablement similaires - si je calculais l'arbre minimal couvrant à peu près n'importe quel ensemble de langues, je suis presque sûr que Python et Ruby seraient les deux premières feuilles à fusionner en un nœud intermédiaire :-).

Bien sûr, je suis fatigué, en Ruby, de taper la "fin" idiote à la fin de chaque bloc (plutôt que de simplement indenter) - mais alors j'arrive à éviter de taper le tout aussi idiot ':' dont Python a besoin à le début de chaque bloc, c'est donc presque un lavage :-). D'autres différences de syntaxe telles que '@foo' contre 'self.foo', ou la signification plus élevée de la casse dans Ruby vs Python, sont vraiment à peu près aussi hors de propos pour moi.

D'autres fondent sans aucun 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 d'une des lois de Parkinson en action (le montant du débat sur une question est inversement proportionnel à celui de la question). importance réelle).

Éditer (by AM 6/19/2010 11:45): c'est aussi connu comme "la peinture du bikeshed" (ou, pour faire court, "bikeshedding") - la référence est, encore une fois, à Northcote Parkinson, qui a donné "des débats" sur quelle couleur peindre le bikeshed "comme exemple typique de" débats chauds sur des sujets triviaux ". (fin d'édition).

Une différence de syntaxe que je trouve importante et en faveur de Python - mais d'autres personnes penseront sans doute juste l'inverse - est "comment appeler 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" - parenthèses de fin juste après l'objet que vous appelez (à l'intérieur de ces parenthèses de fin vont les arguments que vous passez dans l'appel - si vous ne passez aucun argument, les parenthèses sont vides). Cela laisse la simple mention de toutobjet, sans opérateur impliqué, comme signifiant simplement une référence à l'objet - dans n'importe quel contexte, sans cas particuliers, exceptions, règles ad hoc, etc. En 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 pas d'arguments, le simple fait de mentionner la fonction l'appelle implicitement. Cela peut répondre aux attentes de nombreuses personnes (du moins, sans aucun doute, celles dont la seule expérience antérieure de programmation était avec Pascal, ou d'autres langages avec un "appel implicite" similaire, comme Visual Basic) - mais pour moi, cela signifie la simple mention d'un objet peut SOIT signifier une référence à l'objet, OU un appel à l'objet, selon le type d'objet - et dans les cas où je peux ' Pour obtenir une référence à l'objet en le mentionnant simplement, je devrai utiliser une explicite "donnez-moi une référence à cela, ne l'appelez pas!" 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 la possibilité d'interchanger les objets en douceur. Par conséquent, pour moi, cette différence de syntaxe spécifique est une sérieuse marque noire contre Ruby - mais je comprends pourquoi les autres penseraient autrement, même si je ne peux guère être en désaccord avec plus de véhémence avec eux :-). de fonctions (ou de méthodes, ou d'autres objets appelables) et la possibilité d'interchanger des objets en douceur. Par conséquent, pour moi, cette différence de syntaxe spécifique est une sérieuse marque noire contre Ruby - mais je comprends pourquoi les autres penseraient autrement, même si je ne peux guère être en désaccord avec plus de véhémence avec eux :-). de fonctions (ou de méthodes, ou d'autres objets appelables) et la possibilité d'interchanger des objets en douceur. Par conséquent, pour moi, cette différence de syntaxe spécifique est une sérieuse marque noire contre Ruby - mais je comprends pourquoi les autres penseraient autrement, même si je ne peux guère être en désaccord avec plus de véhémence avec eux :-).

En dessous de la syntaxe, nous entrons dans quelques différences importantes dans la sémantique élémentaire - par exemple, les chaînes en Ruby sont des objets mutables (comme en C ++), tandis qu'en Python elles ne sont pas mutables (comme en Java, ou je crois en C #). Encore une fois, les gens qui jugent principalement en fonction de ce qu'ils connaissent déjà peuvent penser que c'est un plus pour Ruby (à moins qu'ils ne connaissent Java ou C #, bien sûr :-). Moi, je pense que les chaînes immuables sont une excellente idée (et je ne suis pas surpris que Java, indépendamment 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 de "tampon de chaîne mutable" (et idéalement avec une meilleure facilité d'utilisation que les propres "tampons de chaîne" de Java); et je ne donne pas ce jugement par familiarité - avant d'étudier Java, toutes les données sont immuables, tous les langages que je connaissais avaient des chaînes mutables - pourtant, quand j'ai vu pour la première fois l'idée de chaîne immuable en Java (que j'ai apprise bien avant d'apprendre Python), cela m'a tout de suite semblé excellent, un très bon ajustement pour la sémantique de référence d'un langage de programmation de niveau supérieur (par opposition à la sémantique de valeur qui correspond le mieux aux langages plus proches de la machine et plus éloignés des applications, telles que C) avec des chaînes en tant que première classe, intégrées (et jolies crucial) type de données.

Ruby présente certains avantages en sémantique élémentaire - par exemple, la suppression de la distinction "listes vs tuples" de Python extrêmement subtile. Mais la plupart du temps (comme je le garde, avec simplicité un gros plus et des distinctions intelligentes subtiles un inconvénient notable) est contre Ruby (par exemple, ayant des intervalles fermés et semi-ouverts, avec les notations a..b et a .. .b [quelqu'un veut prétendre qu'il est évident qui est lequel? -)], est idiot - à mon humble avis , bien sûr!). Encore une fois, les gens qui envisagent d'avoir beaucoup de choses similaires mais subtilement différentes au cœur d'une langue, un PLUS, plutôt qu'un MINUS, les compteront bien sûr "à l'inverse" de la façon dont je les compte :-).

Ne vous laissez pas induire en erreur par ces comparaisons en pensant que les deux langues sont trèsdifférent, attention. Ils ne le sont pas. Mais si on me demande de comparer "capelli d'angelo" à "spaghettini", après avoir souligné que ces deux sortes de pâtes sont à peu près indiscernables pour tout le monde et interchangeables dans n'importe quel plat que vous pourriez vouloir préparer, j'aurais alors inévitablement pour passer à l'examen microscopique de la façon dont les longueurs et les diamètres diffèrent imperceptiblement, comment les extrémités des brins sont effilées dans un cas et non dans l'autre, et ainsi de suite - pour essayer d'expliquer pourquoi je préférerais personnellement avoir capelli d 'angelo comme pâtes dans tout type de bouillon, mais préféreraient les spaghettinis comme pastasciutta pour accompagner des sauces appropriées pour de telles formes de pâtes longues et minces (huile d'olive, ail haché, poivrons rouges hachés et anchois finement moulus, par exemple - mais si vous coupez l'ail et les poivrons au lieu de les hacher, alors vous devriez choisir le corps plus sain des spaghettis plutôt que l'évanescence plus mince des spaghettinis, et il serait bien conseillé de renoncer aux achovies et d'ajouter à la place du basilic frais du printemps [ ou même - je suis hérétique ...! - feuilles de menthe claire ...] - au tout dernier moment avant de servir le plat). Oups, désolé, cela montre que je voyage à l'étranger et que je n'ai pas eu de pâtes depuis un certain temps, je suppose. Mais l'analogie est encore assez bonne! -) - feuilles de menthe claire ...] - au tout dernier moment avant de servir le plat). Oups, désolé, cela montre que je voyage à l'étranger et que je n'ai pas eu de pâtes depuis un certain temps, je suppose. Mais l'analogie est encore assez bonne! -) - feuilles de menthe claire ...] - au tout dernier moment avant de servir le plat). Oups, désolé, cela montre que je voyage à l'étranger et que je n'ai pas eu de pâtes depuis un certain temps, je suppose. Mais l'analogie est encore assez bonne! -)

Donc, revenons à Python et Ruby, nous arrivons aux deux gros trucs (en termes de langage proprement dit - quitter les bibliothèques et autres accessoires importants tels que les outils et les environnements, comment incorporer / étendre chaque langue, etc., etc., hors de pour l'instant - ils ne s'appliqueraient de toute façon pas à toutes les MISES EN ŒUVRE de chaque langue, par exemple, Jython vs Classic Python étant deux implémentations du langage Python!):

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

  2. Ruby TOTAL, la "dynamicité" débridée, y compris la possibilité
    de "rouvrir" n'importe quelle classe existante, y compris toutes les classes intégrées, et de changer son comportement au moment de l'exécution - par rapport à la dynamicité vaste mais limitée de Python, qui ne change jamais le comportement des classes existantes classes intégrées et leurs instances.

Personnellement, je considère 1 comme un lavage (les différences sont si profondes que je pouvais facilement voir des gens détester l'une ou l'autre et vénérer l'autre, mais sur MES échelles personnelles, les avantages et les inconvénients sont à peu près égaux); et 2 une question cruciale - qui rend Ruby beaucoup plus adapté au "bricolage", MAIS Python est également plus adapté à une utilisation dans des applications de grande production. C'est drôle, d'une certaine manière, parce que les deux langues sont tellement beaucoup plus dynamiques que la plupart des autres, qu'à la fin la différence clé entre elles et mon POV devrait reposer sur cela - que Ruby "va à onze" à cet égard (la référence voici "Spinal Tap", bien sûr). En Ruby,JE PEUX FAIRE CELA ! C'est-à-dire que je peux modifier dynamiquement la classe de chaîne intégrée pour que a = "Hello World" b = "hello world" si a == b print "égal! \ N" else print "différent! \ N" end WILL print " égal". En python, il n'y a AUCUN moyen de le faire. Aux fins de la métaprogrammation, de la mise en œuvre de cadres expérimentaux, etc., cette incroyable capacité dynamique de Ruby est extrêmement attirant. MAIS - si nous parlons de grandes applications, développées par de nombreuses personnes et maintenues par encore plus, y compris toutes sortes de bibliothèques de sources diverses, et devant être mises en production sur les sites clients ... eh bien, je ne VEUX PAS une langue assez dynamique, merci beaucoup. Je déteste l'idée même d'une bibliothèque qui casse involontairement d'autres non liées qui dépendent de ces chaînes différentes - c'est le genre de "canal" profond et profondément caché, entre des morceaux de code qui semblent séparés et DEVRAIENT ÊTRE séparés, qui annonce 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,

Si je devais utiliser Ruby pour une application aussi grande, j'essaierais de me fier à des restrictions de style de codage, à 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 fonction de langue. Mais ne pas avoir la fonctionnalité en premier lieu est encore mieux, à mon avis - tout comme Python lui-même serait un langage encore meilleur pour la programmation d'applications si un certain nombre de modules intégrés pouvaient être "cloués", donc je savais que , par exemple, len ( « ciao ») est 4 (plutôt que d' avoir à se soucier de savoir si quelqu'un subliminale a changé la liaison du nom « len » dans le builtins module ...). J'espère que finalement Python "clouera" ses fonctions intégrées.

Mais le problème est mineur, car la reliure des éléments intégrés est assez obsolète ainsi qu'une pratique rare en Python. Dans Ruby, cela me semble majeur - tout comme les fonctionnalités macro trop puissantes d'autres langues (comme, par exemple, Dylan) présentent des risques similaires à mon avis (j'espère que Python n'obtiendra jamais un système macro aussi puissant, non importe l'attrait de «laisser les gens définir leurs propres langages spécifiques au domaine incorporés dans le langage lui-même» - cela, à mon humble avis, nuirait à la merveilleuse utilité de Python pour la programmation d'applications, en présentant une «nuisance attrayante» pour le bricoleur potentiel qui se cache dans le cœur de chaque programmeur ...).

Alex

OscarRyz
la source
9

Quelques autres de:

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

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

Les chaînes sont modifiables en Ruby, pas en Python (où de nouvelles chaînes sont créées par des «changements»).

Ruby a quelques conventions de cas forcé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. Dans Ruby, c'est toujours via des méthodes.

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

Ruby est public, privé et protégé pour imposer l'accès, au lieu de la convention de Python d'utiliser des traits de soulignement et des changements de nom.

Python a un héritage multiple. Ruby a des "mixins".

Et un autre lien très pertinent:

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

Ce qui, en particulier, renvoie à un autre bon par Alex Martelli , qui a également publié beaucoup de bonnes choses ici sur SO:

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

Anon
la source
1
En rubis, vous pouvez simplement geler votre tableau pour le changer en quelque chose d'immuable
user163365
Excellent post par Alex Martelli :)
Skilldrick
8

Je ne suis pas sûr de cela, alors je l'ajoute 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 petite en Python et inexistante en Python 3, elle n'existe pas non plus dans Ruby, simplement parce que Ruby n'a pas de 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 lier à l'objet que vous souhaitez appeler, ce qui est beaucoup plus obstiné.

Lennart Regebro
la source
Ruby n'a pas de fonctions du tout. Cela dit, ce TheClass.instance_method(:themethod).bind(anobject).callserait le rubis équivalent.
Logan Capaldo
Oh. Il y a donc une sorte de classe principale magique lorsque vous définissez une fonction qui n'est pas sur une classe explicite?
Lennart Regebro
Oui, les méthodes définies au niveau supérieur sont des méthodes privées de Object.
Logan Capaldo
1
FWIW, il semble qu'en Python, les fonctions et méthodes sont en fait du même type, et leur comportement différent provient des descripteurs: users.rcn.com/python/download/… .
Bastien Léonard
1
Mais si vous le liez à un objet, il n'est pas non lié. Duh. :-) Et c'est la même chose en Python aussi. C'est juste que Ruby n'a pas de fonctions. Et cela signifie que ma déclaration est correcte. Vous pouvez appeler une méthode non liée comme s'il s'agissait d'une fonction en Python. Et c'est réellement utile, cela signifie par exemple que vous pouvez appeler une méthode définie sur une classe sur un objet qui n'a pas cette classe, ce qui est parfois utile.
Lennart Regebro
7

Je voudrais mentionner l'API de descripteur Python qui permet de personnaliser la "communication" objet à attribut. Il est également à noter qu'en Python, on 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 __getattribute__méthode. Permettez-moi de donner plus de détails sur ce qui précède. Descripteurs sont des classes régulières avec __get__, __set__et / ou __delete__méthodes. Lorsque l'interpréteur rencontre quelque chose comme anObj.anAttr, les opérations suivantes sont effectuées:

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

Comme cela a été mentionné, c'est le 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.

Giorgi
la source
6

Ruby a intégré la prise en charge de la continuation à l'aide de callcc.

Par conséquent, vous pouvez implémenter des choses intéressantes comme l' opérateur amb

Dario
la source
Je souhaite avoir compris callcc. Pouvez-vous donner un scénario d'application plus banal que celui de McCarthy Ambiguous Operator, pour apprécier ses erreurs? Je veux dire quelque chose du monde réel, pas ce truc CS génial?!
ThomasH
"Funky CS stuff" est réel. Prenez le temps d'apprendre: intertwingly.net/blog/2005/04/13/Continuations-for-Curmudgeons
Stephen Eilert
6

À ce stade, Python a toujours un meilleur support Unicode

John La Rooy
la source
5

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

Ps. Si je me trompe, je vous en prie, laissez un exemple? J'ai une solution de contournement que je pourrais facilement monkeypatch dans les classes, mais je voudrais avoir une sorte de fonctionnalité docstring de "manière native".

rasjani
la source
3
n'a pas de docstring, mais a RDoc. Alors oui, pas aussi facilement accessible, mais pas 100% caché.
Omar Qureshi
Ruby n'utilise pas de docstrings. Il fait la documentation d'une manière différente.
Chuck
1
Omar: oui, je connais rdoc mais afaik, ils ne sont pas "aussi accessibles" que les docstrings de python. Par exemple, si j'ai une classe et que je veux sortir la documentation rdoc de la classe, c'est un travail assez lourd. Ce que j'ai fait, c'est que je génère de la documentation ri que j'essaie de garder up2date puis de récupérer cette information vi ri elle-même. Certainement pas au même niveau que les docstrings de python ..
rasjani
Les docstrings peuvent être utilisés pour fournir des doctests. Y a-t-il quelque chose comme ça pour Ruby?
Lennart Regebro
2
Oui, ça s'appelle "Ruby Doctest". En ce qui concerne les doctests, tout ce qui compte vraiment, c'est que vous ayez une documentation lisible quelque part qui inclut des extraits de code testables - cela ne fait aucune différence que ce soit dans une docstring ou dans un commentaire.
Chuck
5

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

ruby -ne 'END {puts $.}'

comptera les lignes comme l'AWK one-liner:

awk 'END{print NR}'

Ruby obtient cette fonctionnalité via Perl, qui l'a emprunté à AWK comme moyen d'obtenir des administrateurs système avec Perl sans avoir à changer leur façon de faire.

Pinochle
la source
1
Je voudrais ajouter que le support de la ligne de commande de Python est plutôt faible. En plus de la boucle automatique manquante, vous ne pouvez pas mettre quelques instructions sur une seule ligne et la transmettre en tant qu'argument de ligne de commande à chaîne unique à l'interpréteur. Au moins, je ne l'ai pas fait.
ThomasH
Bien sûr vous pouvez. Mais vous devrez (comme avec toute autre langue) joindre entre guillemets.
Lennart Regebro
Python n'est pas fait pour être utilisé sur la ligne de commande, car vous devez être explicite sur certaines choses (comme sys.stdin) si vous voulez l'utiliser de cette façonpython -c "import sys; print len(list(sys.stdin))"
u0b34a0f6ae
5

Ruby a des sceaux et des brindilles, Python non.

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

Python a un compilateur JIT ( Psyco ), un langage de niveau nettement inférieur pour écrire du code plus rapide ( Pyrex ) et la possibilité d'ajouter du code C ++ en ligne ( Weave ).

fortran
la source
C'est vrai, mais c'est juste de la syntaxe.
Lennart Regebro
6
Eh bien, si vous voulez emprunter cette voie: les deux sont Turing-complete. Tout le reste n'est que de la syntaxe.
Jörg W Mittag
Oui et une différence de syntaxe d'importation ;-)
fortran
1
En quoi est-ce important si vous écrivez @foo ou self.foo?
Lennart Regebro
1
@ Jörg: OK, appelez-le alors autre chose que "syntaxe". Le fait est que @foo et self.foo font la même chose, ce n'est pas en fait une fonctionnalité de Ruby et pas de Python.
Lennart Regebro
5

Mon python est rouillé, donc certains d'entre eux peuvent être en python et je ne me souviens pas / jamais appris en premier lieu, mais voici les premiers auxquels j'ai pensé:

Espace blanc

Ruby gère les espaces complètement différents. Pour commencer, vous n'avez rien à mettre en retrait (ce qui signifie que peu importe si vous utilisez 4 espaces ou 1 tabulation). Il fait également la continuation de la ligne intelligente, donc ce qui suit est valide:

def foo(bar,
        cow)

Fondamentalement, si vous vous retrouvez avec un opérateur, il comprend ce qui se passe.

Mixins

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

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

Enums

Je ne sais pas si c'est la même chose que les générateurs, mais à partir de Ruby 1.9 ruby ​​comme enums, donc

>> 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 relatifs aux mots clés"

Les deux éléments répertoriés ici sont pris en charge dans Ruby, bien que vous ne puissiez pas ignorer les valeurs par défaut comme ça. 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 en fait la variable c dans la portée appelante la valeur 5, et définit le paramètre b la valeur 5.

ou vous pouvez le faire avec des hachages, qui répondent au 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 de Ruby

Scott Dugas
la source
Votre deuxième exemple foo (1, c = 5) ne fait pas ce que vous pensez qu'il fait. Ruby n'a pas de paramètres nommés.
horseyguy
5
Python a une continuation de ligne implicite entre crochets (, [ou{
u0b34a0f6ae
5

Vous pouvez avoir du code dans la définition de classe dans Ruby et Python. Cependant, dans Ruby, vous avez une référence à la classe (self). En 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 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.

Lennart Regebro
la source
Pouvez-vous fournir plus de détails (comme le code) pour votre premier point?
Loïc Wolff
Un exemple de code est une bonne idée, j'ai ajouté cela, même si ce cas est trivial.
Lennart Regebro
@ SilentGhost: Je ne peux pas penser à celui qui n'est pas vraiment obscur en ce moment. :)
Lennart Regebro
vous pouvez accéder au nom de la classe à l'intérieur de la classe en python: class foo (): def init __ (self): print self .__ class .__ name__
txwikinger
1
@txwikinger: oui, mais pas dans le corps de la classe, qui est exécuté en même temps que l' classinstruction.
Bastien Léonard
4

La syntaxe n'est pas une chose mineure, elle a un impact direct sur notre façon de penser. Il a également un effet direct sur les règles que nous créons pour les systèmes que nous utilisons. Par 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 façons et d'arriver à des réponses différentes selon la même équation. Si nous avions utilisé la notation préfixe ou postfixe, nous aurions créé des règles pour distinguer les nombres à manipuler plutôt que d'avoir uniquement des règles pour l'ordre dans lequel calculer les valeurs.

La notation standard indique clairement les nombres dont nous parlons tout en rendant ambiguë l'ordre dans lequel les calculer. La notation des préfixes et des suffixes rend l'ordre de calcul simple tout en rendant les nombres ambigus. Python aurait déjà des lambdas multilignes sans les 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 plus facile d'écrire des conditions où je veux que quelque chose se produise si une condition est fausse beaucoup plus facile à écrire avec l'instruction à moins en Ruby que la construction sémantiquement équivalente "sinon" en Ruby ou dans d'autres langages par exemple. Si la plupart des langues que les gens utilisent aujourd'hui sont de puissance égale, comment la syntaxe de chaque langue peut-elle être considérée comme une chose banale? Après des fonctionnalités spécifiques comme les blocs et les mécanismes d'héritage, etc., la syntaxe est la partie la plus importante d'un langage, à peine une chose 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, la syntaxe le fait.

compétence ombre
la source
Ce "commentaire" est trois fois plus long que ce qui est autorisé dans un commentaire, quel que soit le représentant.
Andrew Grimm
Cela me semble très bien comme réponse. Modifié le bit "ceci est un commentaire".
Bill the Lizard
3

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

MikeIsGo
la source
Python a get_attribute , qui accomplit fondamentalement la même chose que method_missing de Ruby.
mipadi
3
Pourquoi les développeurs de python sont-ils toujours si blessés quand Ruby est mentionné PARTOUT? Vous ne pouvez pas nier que ce n'est pas vrai.
aarona
method_missingpeut être émulé en Python dans certains cas: class M(): def __getattr__(self, n): return lambda: "Missing! " + n; M().hi(). Cependant, il y a de légères différences et je doute que ce soit idiomatique en Python :-)
1
@DJTripleThreat: Je nie que ce soit vrai.
Lennart Regebro
3

Une autre différence de lambdas entre Python et Ruby est démontrée par le problème du générateur d'accumulateurs de Paul Graham . Réimprimé ici:

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

Dans Ruby, vous pouvez le faire:

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 Python explicite comme étant plus claire conceptuellement, même si elle est un peu plus verbeuse. Vous stockez l'état comme vous le faites pour autre chose. Vous avez juste besoin d'envelopper votre tête autour de l'idée d'objets appelables. Mais quelle que soit l'approche que l'on préfère esthétiquement, cela montre un respect dans lequel les lambdas Ruby sont des constructions plus puissantes que celles de Python.

dortoir
la source
3
Vous ne pouvez pas incrémenter de nombres en Python, donc cette restriction n'a aucun sens. En Python, les nombres sont immuables. Si nous le remplaçons par "plus" à la place, la classe est inutile. Par conséquent, cela ne démontre rien de la différence lambda, mais la différence dans la façon dont les chiffres fonctionnent. À moins bien sûr que vous ne créiez une classe de nombres mutables. :)
Lennart Regebro
2
La restriction est là pour clarifier le comportement souhaité. Ce que le problème demande, c'est: f = foo (10) f (2) >> 12 f (3) >> 15 ... lambda {| i | n + i} donne: f = foo (10) f (2) >> 12 f (3) >> 13 ... Les nombres sont également immuables dans Ruby - vous ne pouvez pas dire 2 + = 1 par exemple. Et n + = 1 est bien dans une fonction Python régulière, mais pas un lambda. Il s'agit donc de savoir ce que "n" est, le fait qu'il est créé lorsque la fonction est invoquée et que le lambda est formé, que vous pouvez faire une affectation dans un lambda (au lieu de simplement des expressions), et qu'il peut contenir la valeur de n sur plusieurs appels.
dormsbee
Je ne pense pas que vous ayez besoin d'aller aussi loin en Python. Les fonctions peuvent être définies dans d'autres fonctions. def foo(n): def f(i): return n + i return f.
FMc
2
Ce n'est toujours pas la même chose, et votre exemple est équivalent au lambda Python dans le commentaire ci-dessus. La version Ruby crée un lambda qui maintient l'état entre les appels. L'exemple que vous avez publié vous permet de configurer une valeur de départ pour n, mais la fonction renvoyée par foo aura toujours cette valeur de départ. La version Ruby s'incrémente. Disons donc f = foo (10). La version Python: f (1) => 11, f (1) => 11. La version Ruby f.call (1) => 11, f.call (1) => 12.
dormsbee
def foo(n): L=[n] def f(i): L[0] += i return L[0] return f. En Python3, vous pouvez utiliser un nonlocalmot-clé.
jfs
3

python a nommé des arguments facultatifs

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

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

AFAIK Ruby n'a positionné que des arguments car b = 2 dans la déclaration de fonction est une affectation qui s'ajoute toujours.

Batiste Bieler
la source
3
que signifie "Ruby n'a positionné que des arguments parce que b = 2 dans la déclaration de fonction est une affectation qui ajoute toujours" signifie même?
horseyguy
3
Vous ne savez pas sur quelle planète vous vivez, mais def my_method(param1, optional = false)fonctionne dans Ruby 1.8.6, 1.8.7 et probablement 1.9!
Robert K
5
The Wicked Flea, et les gens qui ont voté pour son commentaire, vous n'avez pas regardé l'exemple suffisamment près. Il est capable de sauter le bparamètre dans l' funcappel et il conserve toujours sa valeur par défaut. Autrement dit, best le deuxième argument de la signature, mais il peut l'ignorer en préfixant le deuxième paramètre avec c=. Ruby utilise des hachages pour simuler cela, mais ce n'est pas exactement la même chose.
maček
2

Ruby a une documentation intégrée:

 =begin

 You could use rdoc to generate man pages from this documentation

 =end
ko-dos
la source
5
Les docstrings finissent par faire partie des méthodes / classes sur lesquelles vous les définissez. Vous pouvez donc faire de l'aide (classe) et il vous montrera les docstrings, etc.
Lennart Regebro
2

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.

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 = importation ("foo-2.0.0")
>> Foo1 :: VERSION
=> "1.0.0"
>> Foo2 :: VERSION
=> "2.0.0"
Jonas Elfström
la source
Cela aurait plutôt dû être un commentaire, pas une nouvelle réponse.
Lennart Regebro le