Hay muchas discusiones sobre Python vs Ruby, y todas las encuentro completamente inútiles, porque todas dan vueltas por qué la característica X es una mierda en el lenguaje Y, o eso afirma que el lenguaje Y no tiene X, aunque en realidad sí lo tiene. También sé exactamente por qué prefiero Python, pero eso también es subjetivo, y no ayudaría a nadie a elegir, ya que es posible que no tengan los mismos gustos en desarrollo que yo.
Por lo tanto, sería interesante enumerar las diferencias de manera objetiva. Así que no "las lambdas de Python apestan". En cambio, explique lo que las lambdas de Ruby pueden hacer que Python no puede hacer. Sin subjetividad. ¡El código de ejemplo es bueno!
No tenga varias diferencias en una respuesta, por favor. Y vote por los que sabe que son correctos, y por los que sabe que son incorrectos (o subjetivos). Además, las diferencias en la sintaxis no son interesantes. Sabemos que Python hace con sangría lo que Ruby hace con corchetes y extremos, y que @ se llama self en Python.
ACTUALIZACIÓN: Esta es ahora una wiki comunitaria, por lo que podemos agregar las grandes diferencias aquí.
Ruby tiene una referencia de clase en el cuerpo de la clase.
En Ruby tienes una referencia a la clase (self) que ya está en el cuerpo de la clase. En Python, no tiene una referencia a la clase hasta que finaliza la construcción de la clase.
Un ejemplo:
class Kaka
puts self
end
self en este caso es la clase, y este código imprimirá "Kaka". No hay forma de imprimir el nombre de la clase o de otra manera acceder a la clase desde el cuerpo de definición de clase en Python (definiciones de método externas).
Todas las clases son mutables en Ruby.
Esto le permite desarrollar extensiones para las clases principales. Aquí hay un ejemplo de una extensión de rieles:
class String
def starts_with?(other)
head = self[0, other.length]
head == other
end
end
Python (imagina que no hubiera ''.startswith
método):
def starts_with(s, prefix):
return s[:len(prefix)] == prefix
Puede usarlo en cualquier secuencia (no solo cadenas). Con el fin de utilizarlo debe importar que explícitamente por ejemplo, from some_module import starts_with
.
Ruby tiene características de script similares a Perl
Ruby tiene expresiones regulares de primera clase, $ -variables, el bucle de entrada línea por línea awk / perl y otras características que lo hacen más adecuado para escribir pequeños scripts de shell que combinan archivos de texto o actúan como código de pegamento para otros programas.
Ruby tiene continuaciones de primera clase.
Gracias a la declaración callcc. En Python puede crear continuaciones mediante diversas técnicas, pero no hay soporte integrado en el lenguaje.
Ruby tiene bloques
Con la instrucción "do" puede crear una función anónima de varias líneas en Ruby, que se pasará como un argumento al método frente a do, y se llamará desde allí. En Python, en su lugar, haría esto ya sea pasando un método o con generadores.
Rubí:
amethod { |here|
many=lines+of+code
goes(here)
}
Python (los bloques Ruby corresponden a diferentes construcciones en 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
Curiosamente, la declaración de conveniencia en Ruby para llamar a un bloque se llama "rendimiento", que en Python creará un generador.
Rubí:
def themethod
yield 5
end
themethod do |foo|
puts foo
end
Pitón:
def themethod():
yield 5
for foo in themethod():
print foo
Aunque los principios son diferentes, el resultado es sorprendentemente similar.
Ruby admite la programación de estilo funcional (similar a una tubería) más fácilmente
myList.map(&:description).reject(&:empty?).join("\n")
Pitón:
descriptions = (f.description() for f in mylist)
"\n".join(filter(len, descriptions))
Python tiene generadores integrados (que se usan como bloques Ruby, como se señaló anteriormente)
Python tiene soporte para generadores en el lenguaje. En Ruby 1.8 puede usar el módulo generador que usa las continuaciones para crear un generador a partir de un bloque. O bien, ¡podría usar un bloque / proc / lambda! Además, en Ruby 1.9 las fibras son, y se pueden usar como, generadores, y la clase Enumerator es un generador incorporado 4
docs.python.org tiene este ejemplo de generador:
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
Contraste esto con los ejemplos de bloques anteriores.
Python tiene un manejo flexible del espacio de nombres
En Ruby, cuando importa un archivo con require
, todas las cosas definidas en ese archivo terminarán en su espacio de nombres global. Esto causa la contaminación del espacio de nombres. La solución a eso son los módulos Rubys. Pero si crea un espacio de nombres con un módulo, entonces debe usar ese espacio de nombres para acceder a las clases contenidas.
En Python, el archivo es un módulo y puede importar sus nombres contenidos from themodule import *
, contaminando así el espacio de nombres si lo desea. Pero también puede importar nombres seleccionados con from themodule import aname, another
o simplemente puede import themodule
y luego acceder a los nombres con themodule.aname
. Si desea más niveles en su espacio de nombres, puede tener paquetes, que son directorios con módulos y un __init__.py
archivo.
Python tiene docstrings
Las cadenas de documentos son cadenas que se adjuntan a módulos, funciones y métodos y pueden introspectarse en tiempo de ejecución. Esto ayuda a crear cosas como el comando de ayuda y la documentación automática.
def frobnicate(bar):
"""frobnicate takes a bar and frobnicates it
>>> bar = Bar()
>>> bar.is_frobnicated()
False
>>> frobnicate(bar)
>>> bar.is_frobnicated()
True
"""
Los equivalentes de Ruby son similares a los javadocs, y se encuentran sobre el método en lugar de dentro de él. Se pueden recuperar en tiempo de ejecución de los archivos mediante el uso del ejemplo del método # source_location 1.9 de 1.9
Python tiene herencia múltiple
Ruby no lo hace ("a propósito" - vea el sitio web de Ruby, vea aquí cómo se hace en Ruby ). Reutiliza el concepto de módulo como un tipo de clases abstractas.
Python tiene comprensiones de listas / dict
Pitón:
res = [x*x for x in range(1, 10)]
Rubí:
res = (0..9).map { |x| x * x }
Pitón:
>>> (x*x for x in range(10))
<generator object <genexpr> at 0xb7c1ccd4>
>>> list(_)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Rubí:
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'}
Rubí:
>> Hash[{1=>2, 3=>4}.map{|x,y| [x,(y*y).to_s]}]
=> {1=>"4", 3=>"16"}
Python tiene decoradores
También se pueden crear cosas similares a los decoradores en Ruby, y también se puede argumentar que no son tan necesarios como en Python.
Diferencias de sintaxis
Ruby requiere "fin" o "}" para cerrar todos sus ámbitos, mientras que Python usa solo espacios en blanco. Ha habido intentos recientes en Ruby para permitir espacios en blanco solo sangría http://github.com/michaeledgar/seamless