Ci sono molte discussioni su Python vs Ruby, e tutte le trovo del tutto inutili, perché girano tutte intorno al motivo per cui la caratteristica X fa schifo nella lingua Y, o che afferma che la lingua Y non ha X, anche se in realtà lo è. So anche esattamente perché preferisco Python, ma è anche soggettivo e non aiuterebbe nessuno a scegliere, poiché potrebbero non avere gli stessi gusti nello sviluppo di me.
Sarebbe quindi interessante elencare le differenze, obiettivamente. Quindi nessun "lambda di Python fa schifo". Spiega invece cosa possono fare gli lambda di Ruby che Python non può fare. Nessuna soggettività Il codice di esempio è buono!
Non avere diverse differenze in una risposta, per favore. E vota quelli che conosci sono corretti e quelli che conosci sono errati (o soggettivi). Inoltre, le differenze di sintassi non sono interessanti. Sappiamo che Python fa con indentazione ciò che Ruby fa con parentesi e punte, e che @ è chiamato sé in Python.
AGGIORNAMENTO: Questo è ora un wiki della comunità, quindi possiamo aggiungere qui le grandi differenze.
Ruby ha un riferimento di classe nel corpo della classe
In Ruby hai un riferimento alla classe (sé) già nel corpo della classe. In Python non hai un riferimento alla classe fino al termine della costruzione della classe.
Un esempio:
class Kaka
puts self
end
self in questo caso è la classe e questo codice stampa "Kaka". Non è possibile stampare il nome della classe o accedere in altro modo alla classe dal corpo della definizione della classe in Python (definizioni del metodo esterno).
Tutte le classi sono mutabili in Ruby
Ciò consente di sviluppare estensioni per le classi principali. Ecco un esempio di estensione di rotaie:
class String
def starts_with?(other)
head = self[0, other.length]
head == other
end
end
Python (immagina che non esistesse un ''.startswith
metodo):
def starts_with(s, prefix):
return s[:len(prefix)] == prefix
Potresti usarlo su qualsiasi sequenza (non solo sulle stringhe). Per poterlo utilizzare è necessario importarlo esplicitamente , ad es from some_module import starts_with
.
Ruby ha funzionalità di scripting simili al Perl
Ruby ha regexps di prima classe, $ -variables, il ciclo di input riga per riga awk / perl e altre funzionalità che lo rendono più adatto alla scrittura di piccoli script shell che coprono file di testo o fungono da codice colla per altri programmi.
Ruby ha continuazioni di prima classe
Grazie all'istruzione callcc. In Python puoi creare continuazioni con varie tecniche, ma non c'è supporto integrato nel linguaggio.
Ruby ha dei blocchi
Con l'istruzione "do" è possibile creare una funzione anonima multilinea in Ruby, che verrà passata come argomento nel metodo di fronte a do e chiamata da lì. In Python lo faresti invece passando un metodo o con generatori.
Rubino:
amethod { |here|
many=lines+of+code
goes(here)
}
Python (i blocchi Ruby corrispondono a diversi costrutti in Python):
with amethod() as here: # `amethod() is a context manager
many=lines+of+code
goes(here)
O
for here in amethod(): # `amethod()` is an iterable
many=lines+of+code
goes(here)
O
def function(here):
many=lines+of+code
goes(here)
amethod(function) # `function` is a callback
È interessante notare che la dichiarazione di convenienza in Ruby per chiamare un blocco si chiama "yield", che in Python creerà un generatore.
Rubino:
def themethod
yield 5
end
themethod do |foo|
puts foo
end
Pitone:
def themethod():
yield 5
for foo in themethod():
print foo
Sebbene i principi siano diversi, il risultato è sorprendentemente simile.
Ruby supporta la programmazione di stili funzionali (simili a pipe) più facilmente
myList.map(&:description).reject(&:empty?).join("\n")
Pitone:
descriptions = (f.description() for f in mylist)
"\n".join(filter(len, descriptions))
Python ha generatori integrati (che sono usati come blocchi di Ruby, come notato sopra)
Python supporta i generatori nella lingua. In Ruby 1.8 è possibile utilizzare il modulo generatore che utilizza le continuazioni per creare un generatore da un blocco. Oppure potresti semplicemente usare un blocco / proc / lambda! Inoltre, in Ruby 1.9 le fibre sono e possono essere utilizzate come generatori e la classe Enumerator è un generatore integrato 4
docs.python.org ha questo esempio di generatore:
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
Contrastare questo con gli esempi di blocco sopra.
Python ha una gestione flessibile dello spazio dei nomi
In Ruby, quando importi un file con require
, tutte le cose definite in quel file finiranno nel tuo spazio dei nomi globale. Ciò provoca l'inquinamento dello spazio dei nomi. La soluzione a ciò sono i moduli Rubys. Ma se si crea uno spazio dei nomi con un modulo, è necessario utilizzare quello spazio dei nomi per accedere alle classi contenute.
In Python, il file è un modulo e puoi importare i suoi nomi contenuti con from themodule import *
, inquinando così lo spazio dei nomi se vuoi. Ma puoi anche importare solo i nomi selezionati con from themodule import aname, another
o puoi semplicemente import themodule
e quindi accedere ai nomi con themodule.aname
. Se vuoi più livelli nel tuo spazio dei nomi puoi avere dei pacchetti, che sono directory con moduli e un __init__.py
file.
Python ha dotstrings
Le docstring sono stringhe collegate a moduli, funzioni e metodi e che possono essere introspezionate in fase di esecuzione. Questo aiuta a creare cose come il comando help e la documentazione automatica.
def frobnicate(bar):
"""frobnicate takes a bar and frobnicates it
>>> bar = Bar()
>>> bar.is_frobnicated()
False
>>> frobnicate(bar)
>>> bar.is_frobnicated()
True
"""
L'equivalente di Ruby è simile a javadocs e si trova sopra il metodo anziché all'interno. Possono essere recuperati in fase di runtime dai file usando l' uso dell'esempio # # source_location di 1.9
Python ha eredità multipla
Ruby non lo fa ("apposta" - vedi il sito web di Ruby, vedi qui come è fatto in Ruby ). Riutilizza il concetto di modulo come un tipo di classi astratte.
Python ha una comprensione elenco / dettatura
Pitone:
res = [x*x for x in range(1, 10)]
Rubino:
res = (0..9).map { |x| x * x }
Pitone:
>>> (x*x for x in range(10))
<generator object <genexpr> at 0xb7c1ccd4>
>>> list(_)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Rubino:
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'}
Rubino:
>> Hash[{1=>2, 3=>4}.map{|x,y| [x,(y*y).to_s]}]
=> {1=>"4", 3=>"16"}
Python ha decoratori
Cose simili ai decoratori possono anche essere create in Ruby, e si può anche sostenere che non sono necessarie come in Python.
Differenze di sintassi
Ruby richiede "end" o "}" per chiudere tutti i suoi ambiti, mentre Python usa solo spazi bianchi. Ci sono stati recenti tentativi in Ruby di consentire solo il rientro degli spazi bianchi http://github.com/michaeledgar/seamless