¿Qué tiene Ruby que Python no tiene, y viceversa?

| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |

Hay muchas discusiones sobre Python vs. Ruby, y todas las encuentro completamente inútiles, porque todos se preguntan por qué la característica X apesta en el lenguaje Y, o que afirman que el lenguaje Y no tiene X, aunque de hecho 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, objetivamente. Así que ninguna lambda de "Python apesta". En su lugar, explique qué pueden hacer las lambdas de Ruby que no pueden hacer las de Python. Sin subjetividad. ¡El código de ejemplo es bueno!

No tenga varias diferencias en una respuesta, por favor. Y vota hacia arriba por las que sepas que son correctas y hacia abajo por las que sepas que son incorrectas (o subjetivas). Además, las diferencias en la sintaxis no son interesantes. Sabemos que Python hace con la sangría lo que Ruby hace con corchetes y extremos, y que @ se llama self en Python.

ACTUALIZAR: Esta es ahora una wiki de la comunidad, por lo que podemos agregar las grandes diferencias aquí.

Ruby tiene una referencia de clase en el cuerpo de la clase

En Ruby, ya tiene una referencia a la clase (yo) 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:

la clase Kaka se pone fin a sí misma 

self en este caso es la clase, y este código imprimiría "Kaka". No hay forma de imprimir el nombre de la clase o de otras formas acceder a la clase desde el cuerpo de definición de clase en Python (fuera definiciones de métodos).

Todas las clases son mutables en Ruby

Esto le permite desarrollar extensiones para las clases principales. Aquí hay un ejemplo de una extensión Rails:

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

Python (imagina que no hubiera "". comienza con método):

def comienza_con(s, prefijo): return s[:len(prefijo)] == prefijo 

Usted podría usarlo en cualquier secuencia (no solo cadenas). Para usarlo, debe importarlo explícitamente, por ejemplo, desde algún_módulo, la importación comienza_con.

Ruby tiene funciones de secuencias de comandos similares a las de 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 manipulan archivos de texto o actúan como código de unión para otros programas.

Ruby tiene continuaciones de primera clase

Gracias a la instrucción callcc. En Python, puede crear continuaciones mediante varias técnicas, pero no hay soporte integrado en el lenguaje.

Ruby tiene bloques

Con la declaración "do" puede crear un multi- línea función anónima en Ruby, que se pasará como argumento al método delante de do, y se llamará desde allí. En Python, en cambio, haría esto pasando un método o con generadores.

Ruby:

amethod { |here| muchas=líneas+de+código va(aquí) } 

Python (los bloques de Ruby corresponden a diferentes construcciones en Python):

con amethod() como aquí: # `amethod() es un administrador de contexto muchas=líneas+de+código va(aquí) 

O

para aquí en amethod() : # `amethod()` es una iterable muchas=líneas+de+código va(aquí) 

O

función def(aquí): muchos =líneas+de+código va(aquí) un método(función) # `función` es una devolución de llamada 

Curiosamente, la declaración de conveniencia en Ruby para llamar a un bloque se llama "rendimiento", que en Python creará un generador.

Ruby:

def themethod yield 5 end themethod do |foo| pone foo end 

Python:

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 (tipo tubería) más fácilmente

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

Python:

descripciones = (f.description() para f en mi lista) " ".join(filter(len, descripciones)) 

Python tiene generadores integrados (que se usan como bloques de Ruby, como se indicó anteriormente)

Python tiene soporte para generadores en el lenguaje. En Ruby 1.8 puede usar el módulo generador que usa continuaciones para crear un generador a partir de un bloque. ¡O simplemente podría usar un bloque/proc/lambda! Además, en Ruby 1.9, las fibras son y pueden usarse 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] 

Compare 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 provoca la contaminación del espacio de nombres. La solución a eso son los módulos de Rubys. Pero si crea un espacio de nombres con un módulo, 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 con from themodule import *, contaminando así el espacio de nombres si lo desea. Pero también puede importar solo los nombres seleccionados con desde el módulo importar un nombre, otro o puede simplemente importar el módulo 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 archivo __init__.py.

Python tiene docstrings

Docstrings son cadenas que se adjuntan a módulos, funciones y métodos y se pueden introspeccionar 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 toma una barra y la frobnica >>> bar = Bar( ) >>> bar.is_frobnicated() Falso >>> frobnicate(bar) >>> bar.is_frobnicated() True """ 

Ruby Los equivalentes son similares a los javadocs y se ubican sobre el método en lugar de dentro de él. Se pueden recuperar en tiempo de ejecución desde los archivos usando 1.9's Method#source_location uso de ejemplo

Python tiene herencia múltiple

Ruby no ("a propósito" -- ver Sitio web de Ruby, ve aquí cómo "está hecho en Ruby). Reutiliza el concepto de módulo como un tipo de clases abstractas.

Python tiene comprensiones de lista/dict

Python:

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

Ruby:

res = (0..9).map { |x| x * x } 

Python:

>>> (x*x para x en el rango (10)) <objeto generador <genexpr> en 0xb7c1ccd4> >>> lista(_) [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] 

Ruby:

p = proceso { |x| x * x } (0..9).map(&p) 

Python 2.7+:

> ;>> {x:str(y*y) para x,y en {1:2, 3:4}.items()} {1: "4", 3: "16"} 

Rubí:

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

Python tiene decoradores

También se pueden crear elementos 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 "finalizar" o "}" para cerrar todos sus ámbitos, mientras que Python usa solo espacios en blanco. Ha habido intentos recientes en Ruby para permitir solo espacios en blanco sangría http://github.com /michaeledgar/sin costuras