264 votes

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

Il y a beaucoup de discussions de Python vs Ruby, et j'ai tous les trouver complètement inutile, parce qu'elles tournent toutes autour pourquoi la fonctionnalité X suce dans la langue Y, ou que la revendication de la langue Y n'a pas de X, bien qu'en fait il ne. Je sais exactement pourquoi je préfère Python, mais c'est aussi subjective, et ne pas aider quelqu'un à choisir, car ils peuvent ne pas avoir les mêmes goûts en matière de développement que je fais.

Il serait donc intéressant d'énumérer les différences, objectivement. Donc pas de "Python lambdas suce". Au lieu d'expliquer ce que Ruby lambdas peuvent faire que Python ne peut pas. Pas de subjectivité. L'exemple de code est bon!

Ne pas avoir plusieurs différences dans la réponse, s'il vous plaît. Et de voter pour celles qui vous le savez sont corrects, et le bas de ceux que vous connaissez sont incorrectes (ou subjective). En outre, les différences dans la syntaxe n'est pas intéressant. Nous savons Python avec indentation ce que Ruby ne avec des crochets et se termine, et que @ est appelé auto en Python.

Mise à JOUR: C'est maintenant un wiki de la communauté, afin que nous puissions ajouter les grandes différences ici.

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

En Ruby, vous avez une référence à la classe (auto) déjà dans le corps de la classe. En Python, vous n'avez pas une référence à la classe jusqu'à la classe après la classe, la construction est terminée.

Un exemple:

class Kaka
  puts self
end

dans ce cas, c'est la classe, et ce code affichera le "Kaka". Il n'existe aucun moyen pour imprimer le nom de la classe ou dans d'autres façons d'accéder à la classe à partir de la définition de la classe de corps en Python (en dehors des définitions de méthode).

Toutes les classes sont mutables en Ruby

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

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

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

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

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

Ruby, Perl-comme les fonctions script

Ruby a première classe, les expressions régulières, $-variables, le awk/perl ligne par ligne de boucle d'entrée et d'autres fonctionnalités qui le rendent plus adapté à écrire de petits scripts shell munge des fichiers texte ou d'agir comme une colle de code pour d'autres programmes.

Ruby a première classe continuations

Grâce à la callcc déclaration. En Python, vous pouvez créer des poursuites par diverses techniques, mais il n'y a pas de prise en charge intégrée de la langue.

Ruby a des blocs

Avec le "faire" de la déclaration, vous pouvez créer un multi-ligne fonction anonyme en Ruby, qui sera passé en argument à la méthode avant de le faire, et a appelé à partir de là. En Python, vous serait plutôt de le faire soit par le passage d'une méthode ou des générateurs.

Ruby:

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

Python (Ruby blocs correspondent aux 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, la commodité de l'exposé en Ruby pour l'appel d'un bloc est appelé le "rendement", qui en Python va créer un générateur.

Ruby:

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 sont différents, le résultat est étonnamment similaires.

Ruby prend en charge fonctionnelle de style (tube-like) programmation plus facilement

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

Python:

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

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

Python a un support pour les générateurs de la langue. En Ruby 1.8, vous pouvez utiliser le générateur de module qui utilise des continuations pour créer un générateur à partir d'un bloc. Ou, vous pouvez simplement utiliser un bloc de/proc/lambda! En outre, dans Ruby 1.9 Fibres sont, et peuvent être utilisés en tant que générateurs, et la classe Énumérateur est intégré dans le générateur 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]

Ceci contraste avec le bloc ci-dessus des exemples.

Python a flexible de l'espace de nom de manutention

En Ruby, lorsque vous importez un fichier avec l' require, toutes les choses que défini dans ce fichier dans votre espace de noms global. Cela provoque la pollution de l'espace de noms. La solution à cela est Rubys modules. Mais si vous créez un espace de noms avec un module, alors vous devez utiliser l'espace de nom pour accéder au contenu des classes.

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

Python a docstrings

Docstrings sont des chaînes de caractères qui sont attachés à des modules, les fonctions et les méthodes et peut être l'introspection à l'exécution. Cela permet de créer des choses telles que la commande d'aide et documentation automatique.

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

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

Ruby est équivalent sont similaires à la documentation javadoc, et situé au-dessus de la méthode au lieu de l'intérieur. Ils peuvent être récupérées lors de l'exécution de fichiers à l'aide de 1,9 Méthode#source_location exemple d'utilisation

Python est l'héritage multiple

Ruby n'a pas ("" -- voir Ruby site web, voyez ici comment c'est fait en Ruby). Il ne réutiliser le concept de module comme un type de classes abstraites.

Python dispose d'une liste/dict interprétations de la

Python:

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

Ruby:

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]

Ruby:

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

Ruby:

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

Python a décorateurs

Des choses semblables à des décorateurs peuvent également être créés en Ruby, et il peut aussi faire valoir qu'ils ne sont pas aussi nécessaire qu'en Python.

Les différences de syntaxe

Ruby exige "fin" ou "}" pour fermer l'ensemble de ses étendues, tandis que Python utilise un espace blanc. Il y a eu des tentatives récentes en Ruby pour permettre seulement les espaces d'indentation http://github.com/michaeledgar/seamless

34voto

John Feminella Points 116878

Ruby a les concepts de blocs, qui sont essentiellement sucre syntaxique autour d'une section de code; ils sont un moyen de créer des fermetures et les passer à une autre méthode qui peut ou ne peut pas utiliser le bloc. Un bloc peut être appelé plus tard par le biais d'un yield déclaration.

Par exemple, une définition simple de l' each méthode Array pourrait ê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 appeler cela de la sorte:

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

Python a des fonctions anonymes/fermetures/lambdas, mais il n'a pas assez de blocs, car il manque quelques de la durée de sucre syntaxique. Cependant, il y a au moins un moyen d'obtenir de manière ad-hoc. Voir, par exemple, ici.

28voto

Glenn Maynard Points 24451

Exemple Python

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

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

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

C'est une caractéristique fondamentale de moderne, les langages de script. JavaScript et Lua ce faire, trop. Ruby ne permet pas de traiter les fonctions de cette façon; nom d'un des appels de fonction.

Bien sûr, il existe des moyens de faire ces choses en Ruby, mais ils ne sont pas d'abord des opérations de classe. Par exemple, vous pouvez placer une fonction avec Proc.nouvelles de la traiter comme une variable, mais alors ce n'est plus une fonction; c'est un objet avec un "appel" de la méthode.

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

Ruby fonctions ne sont pas des objets de première classe. Les fonctions doivent être encapsulées dans un objet pour les passer autour, et l'objet ne peut pas être traitée comme une fonction. Les fonctions ne peuvent pas être attribués à un de première classe; au lieu de cela, une fonction dans son conteneur d'objet doit être appelé à 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!"    

26voto

Mark Thomas Points 19281

En fin de compte toutes les réponses vont être subjectif à un certain niveau, et les réponses postées jusqu'à présent assez bien prouver que vous ne pouvez pas pointer à une fonctionnalité qui n'est pas faisable dans l'autre langue dans une tout aussi belle (si ce n'est similaire, bien que les deux langues sont très concis et expressif.

J'aime Python syntaxe. Cependant, vous avez à creuser un peu plus profond que la syntaxe pour trouver la vraie beauté de Ruby. Il est zenlike beauté dans le Rubis est la cohérence. Bien qu'aucun exemple trivial peut peut-être expliquer cela complètement, je vais essayer de venir avec un ici juste pour expliquer ce que je veux dire.

Inverser les mots dans cette chaîne:

sentence = "backwards is sentence This"

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

  1. Couper une phrase en mots
  2. Inverser les mots
  3. Re-joindre de nouveau les mots dans une chaîne

En Ruby, vous devrez faire cela:

sentence.split.reverse.join ' '

Exactement comme vous pensez à ce sujet, dans la même séquence, un seul appel de méthode après l'autre.

En python, il serait ressembler à ceci:

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

Il n'est pas difficile à comprendre, mais il n'a pas tout à fait la même. Le sujet (de la phrase) est enterré dans le milieu. Les opérations sont un mélange de fonctions et méthodes de l'objet. C'est un exemple trivial, mais on découvre de nombreux exemples quand vraiment travailler avec et de la compréhension de Ruby, en particulier sur les tâches non négligeables.

18voto

Jason Baker Points 56682

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

Par exemple, Ruby:

 >> PI = 3.14
=> 3.14
>> PI += 1
(irb):2: warning: already initialized constant PI
=> 4.14
 

Python:

 >>> PI = 3.14
>>> PI += 1
>>> PI
4.1400000000000006
 

18voto

Tempus Points 22972

Vous ne pouvez importer que des fonctions spécifiques à partir d'un module en Python. En Ruby, vous devez importer l'ensemble de la liste des méthodes. Vous pourriez "unimport" en Ruby, mais ce n'est pas ce dont il s'agit.

EDIT:

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 method1 et method2 ont été ajoutés à votre espace de noms. Vous ne pouvez pas importer uniquement method1. Vous les importer à la fois ou vous n'avez pas les importer. En Python, vous pouvez importer uniquement les méthodes de votre choix. Si cela aurait un nom peut-être qu'il serait appelé sélective de l'importation?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X