tag - ¿Qué tiene Ruby que Python no tiene, y viceversa?
parser html python (30)
Hay muchas discusiones sobre Python vs Ruby, y todos los encontramos completamente inútiles, porque todos se dan cuenta de por qué la característica X apesta en el lenguaje Y, o que el lenguaje de reclamación Y no tiene X, aunque en realidad sí. También sé exactamente por qué prefiero Python, pero eso también es subjetivo, y no ayudaría a nadie a elegir, ya que podrían no tener los mismos gustos en desarrollo que yo.
Por lo tanto, sería interesante enumerar las diferencias, objetivamente. Así que no hay "lambdas de Python apesta". En vez de eso, explica qué pueden hacer las lambdas de Ruby que Python''s no puede. No hay subjetividad. Código de ejemplo es bueno!
No tengo 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 es interesante. 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 de la comunidad, así 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) ya 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 la definición de la clase en Python (fuera de las definiciones de métodos).
Todas las clases son mutables en Ruby.
Esto te 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 hay ''''.startswith
método"):
def starts_with(s, prefix):
return s[:len(prefix)] == prefix
Podrías usarlo en cualquier secuencia (no solo cadenas). Para usarlo, debe importarlo explícitamente , por ejemplo, from some_module import starts_with
.
Ruby tiene características de scripts similares a Perl
Ruby tiene expresiones regulares de primera clase, variables de $, el bucle de entrada línea a línea awk / perl y otras características que lo hacen más adecuado para escribir scripts de shell pequeños que munge 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 de callcc. En Python puede crear continuaciones mediante varias 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 multilínea en Ruby, que se pasará como un argumento en el método que está delante de do y se llamará desde allí. En Python, en lugar de hacerlo, lo harías pasando un método o con generadores.
Rubí:
amethod { |here|
many=lines+of+code
goes(here)
}
Python (los bloques de 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 incorporados (que se utilizan como bloques de 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 continuaciones para crear un generador a partir de un bloque. O, simplemente puedes 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]
Contrasta 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 de Rubys. Pero si crea un espacio de nombres con un módulo, entonces tiene que 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 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 archivo __init__.py
.
Python tiene cadenas de documentación
Las cadenas de documentación son cadenas que se adjuntan a módulos, funciones y métodos y se pueden analizar en el 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 javadocs y se ubican por encima del método en lugar de dentro de él. Se pueden recuperar en tiempo de ejecución de los archivos utilizando el ejemplo de Método # source_location de 1.9.
Python tiene herencia múltiple
Ruby no ("a propósito": consulte el sitio web de Ruby, vea cómo se hace en Ruby ). Reutiliza el concepto de módulo como un tipo de clases abstractas.
Python tiene lista / dictámenes
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
Las cosas similares a los decoradores también se pueden crear en Ruby, y también se puede argumentar que no son tan necesarias como en Python.
Diferencias de sintaxis
Ruby requiere "finalizar" o "}" para cerrar todos sus ámbitos, mientras que Python solo usa espacios en blanco. Ha habido intentos recientes en Ruby para permitir solo espacios en blanco en espacios en blanco http://github.com/michaeledgar/seamless
En Ruby, cuando importa un archivo con require, todas las cosas definidas en ese archivo terminarán en su espacio de nombres global.
Con Cargo puede " requerir bibliotecas sin saturar su espacio de nombres ".
# 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 = import("foo-2.0.0") >> Foo1::VERSION => "1.0.0" >> Foo2::VERSION => "2.0.0"
Ejemplo de Python
Las funciones son variables de primera clase en Python. Puede declarar una función, pasarla como un objeto y sobrescribirla:
def func(): print "hello"
def another_func(f): f()
another_func(func)
def func2(): print "goodbye"
func = func2
Esta es una característica fundamental de los lenguajes de script modernos. JavaScript y Lua también lo hacen. Ruby no trata las funciones de esta manera; nombrar una función la llama.
Por supuesto, hay formas de hacer estas cosas en Ruby, pero no son operaciones de primera clase. Por ejemplo, puede envolver una función con Proc.new para tratarla como una variable, pero ya no es una función; Es un objeto con un método de "llamada".
Las funciones de Ruby no son objetos de primera clase.
Las funciones de Ruby no son objetos de primera clase. Las funciones deben estar envueltas en un objeto para pasarlas; El objeto resultante no puede ser tratado como una función. Las funciones no se pueden asignar de una manera de primera clase; en su lugar, una función en su objeto contenedor debe ser llamada para modificarlos.
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!"
"Las variables que comienzan con una letra mayúscula se convierten en constantes y no pueden modificarse"
Incorrecto. Ellos pueden.
Sólo recibes una advertencia si lo haces.
De la website de Ruby:
Similitudes Como con Python, en Ruby, ...
- Hay un indicador interactivo (llamado irb).
- Puede leer documentos en la línea de comandos (con el comando ri en lugar de pydoc).
- No hay terminadores de línea especiales (excepto la nueva línea habitual).
- Los literales de cadena pueden abarcar varias líneas, como las cadenas de comillas triples de Python.
- Los corchetes son para listas y los corchetes son para dictos (que, en Ruby, se denominan "hashes").
- Los arreglos funcionan de la misma manera (agregarlos hace un arreglo largo, pero al componerlos así
a3 = [ a1, a2 ]
te da un arreglo de arreglos).- Los objetos son tipificados fuerte y dinámicamente.
- Todo es un objeto, y las variables son solo referencias a objetos.
- Aunque las palabras clave son un poco diferentes, las excepciones funcionan casi igual.
- Tienes herramientas de documentación incrustadas (Ruby''s se llama rdoc).
Diferencias a diferencia de Python, en Ruby, ...
- Las cuerdas son mutables.
- Puedes hacer constantes (variables cuyo valor no pretendes cambiar).
- Hay algunas convenciones de casos forzadas (por ejemplo, los nombres de clase comienzan con una letra mayúscula, las variables comienzan con una letra minúscula).
- Solo hay un tipo de contenedor de lista (una matriz), y es mutable.
- Las cadenas entre comillas dobles permiten secuencias de escape (como / t) y una sintaxis especial de "sustitución de expresión" (que le permite insertar los resultados de las expresiones de Ruby directamente en otras cadenas sin tener que "agregar" + "cadenas" + "juntas") . Las cadenas con comillas simples son como las "cadenas en bruto" de Python.
- No hay clases de "estilo nuevo" y "estilo antiguo". Sólo un tipo.
- Nunca se accede directamente a los atributos. Con Ruby, todo es método de llamadas.
- Los paréntesis para las llamadas a métodos suelen ser opcionales.
- Hay acceso público, privado y protegido para imponer el acceso, en lugar de
_voluntary_ underscore __convention__
de Python_voluntary_ underscore __convention__
.- Se usan "mixin" en lugar de herencia múltiple.
- Puede agregar o modificar los métodos de las clases incorporadas. Ambos idiomas le permiten abrir y modificar clases en cualquier momento, pero Python evita la modificación de elementos integrados, pero Ruby no.
- Tienes verdadero y falso en lugar de Verdadero y Falso (y nulo en lugar de Ninguno).
- Cuando se prueba la verdad, solo falso y nulo se evalúan a un valor falso. Todo lo demás es verdadero (incluidos 0, 0.0, "" y []).
- Es elsif en lugar de elif.
- Es necesario en lugar de importar. De lo contrario, sin embargo, el uso es el mismo.
- Los comentarios de estilo habitual en las líneas anteriores (en lugar de las cadenas de documentación debajo de ellas) se utilizan para generar documentos.
- Hay una serie de atajos que, aunque te dan más para recordar, aprendes rápidamente. Tienden a hacer que Ruby sea divertido y muy productivo.
En última instancia, todas las respuestas serán subjetivas en algún nivel, y las respuestas publicadas hasta ahora demuestran que no se puede señalar ninguna característica que no sea factible en el otro idioma de una manera igualmente agradable (si no similar) , ya que ambas lenguas son muy concisas y expresivas.
Me gusta la sintaxis de Python. Sin embargo, tienes que profundizar un poco más que la sintaxis para encontrar la verdadera belleza de Ruby. Hay belleza zen en la consistencia de Ruby. Si bien ningún ejemplo trivial puede explicar esto completamente, intentaré encontrar uno aquí solo para explicar lo que quiero decir.
Invertir las palabras en esta cadena:
sentence = "backwards is sentence This"
Cuando piensas en cómo lo harías, harías lo siguiente:
- Divide la oración en palabras
- Revertir las palabras
- Re-unir las palabras de nuevo en una cadena
En Ruby, harías esto:
sentence.split.reverse.join '' ''
Exactamente como lo piensas, en la misma secuencia, un método llama tras otro.
En python, se vería más como esto:
" ".join(reversed(sentence.split()))
No es difícil de entender, pero no tiene el mismo flujo. El sujeto (oración) está enterrado en el medio. Las operaciones son una mezcla de funciones y métodos de objeto. Este es un ejemplo trivial, pero uno descubre muchos ejemplos diferentes cuando realmente trabaja y entiende a Ruby, especialmente en tareas no triviales.
Lo que Ruby tiene sobre Python son sus capacidades de lenguaje de scripting. El lenguaje de secuencias de comandos en este contexto significa que se utilizará para el "código de pegamento" en los scripts de shell y la manipulación general de texto.
Estos son en su mayoría compartidos con Perl. Expresiones regulares incorporadas de primera clase, variables-$, opciones de línea de comandos útiles como Perl (-a, -e) etc.
Junto con su sintaxis escasa pero epxresiva, es perfecta para este tipo de tareas.
Python para mí es más bien un lenguaje de negocios de tipo dinámico que es muy fácil de aprender y tiene una sintaxis clara. No tan "cool" como Ruby pero limpio. Lo que Python tiene sobre Ruby para mí es la gran cantidad de enlaces para otras librerías. Enlaces a Qt y otras librerías de GUI, muchas bibliotecas de soporte de juegos y y y. Ruby tiene mucho menos. Mientras que los enlaces más usados, por ejemplo, a las bases de datos, son de buena calidad, encontré que las bibliotecas de nicho son mejor soportadas en Python, incluso si para la misma biblioteca también hay un enlace de Ruby.
Por lo tanto, diría que ambos idiomas tienen su uso y es la tarea la que define cuál usar. Ambos son fáciles de aprender. Los uso lado a lado. Ruby para scripting y Python para aplicaciones independientes.
Me gustaría sugerir una variante de la pregunta original: "¿Qué tiene Ruby que Python no tiene, y viceversa?" que admite la respuesta decepcionante: "Bueno, ¿qué puedes hacer con Ruby o Python que no se puede hacer en Intercal?" Nada en ese nivel, porque Python y Ruby son parte de la vasta familia real sentada en el trono de Turing, que se aproxima.
Pero ¿qué pasa con esto?
¿Qué se puede hacer con gracia y bien en Python que no se pueda hacer en Ruby con tanta belleza y buena ingeniería, o viceversa?
Eso puede ser mucho más interesante que la simple comparación de características.
No creo que "Ruby tenga X y Python no, mientras que Python tenga Y y Ruby no" es la forma más útil de verlo. Son lenguajes bastante similares, con muchas habilidades compartidas.
En gran medida, la diferencia es lo que el lenguaje hace elegante y legible. Para usar un ejemplo que mencionaste, ambos tienen teñidas, pero los programadores de Python tienden a evitarlos, y las construcciones hechas para usarlos no parecen ni tan legibles ni idiomáticas como en Ruby. Entonces, en Python, un buen programador querrá tomar una ruta diferente para resolver el problema que él en Ruby, solo porque en realidad es la mejor manera de hacerlo.
Puede importar solo funciones específicas de un módulo en Python. En Ruby, importas toda la lista de métodos. Puedes "quitarles importancia" a Ruby, pero no se trata de eso.
EDITAR:
Tomemos este módulo de Ruby:
module Whatever
def method1
end
def method2
end
end
Si lo incluyes en tu código:
include Whatever
verá que se han agregado method1 y method2 a su espacio de nombres. No puedes importar solo method1 . Los importas los dos o no los importas en absoluto. En Python solo puedes importar los métodos que elijas. Si esto tuviera un nombre, ¿se llamaría importación selectiva?
Python tiene una mentalidad de "todos somos adultos aquí". Por lo tanto, encontrarás que Ruby tiene cosas como constantes, mientras que Python no (aunque las constantes de Ruby solo muestran una advertencia). La forma de pensar de Python es que si quieres hacer algo constante, debes poner los nombres de las variables en mayúsculas y no cambiarlos.
Por ejemplo, Ruby:
>> PI = 3.14
=> 3.14
>> PI += 1
(irb):2: warning: already initialized constant PI
=> 4.14
Pitón:
>>> PI = 3.14
>>> PI += 1
>>> PI
4.1400000000000006
Python tiene una sintaxis explícita, incorporada para listas de comprensión y generadores, mientras que en Ruby usarías bloques de código y mapa.
Comparar
list = [ x*x for x in range(1, 10) ]
a
res = (1..10).map{ |x| x*x }
Ruby tiene los conceptos de bloques , que son esencialmente azúcar sintáctica en torno a una sección de código; son una forma de crear cierres y pasarlos a otro método que puede o no puede usar el bloque. Un bloque se puede invocar más adelante a través de una declaración de yield
.
Por ejemplo, una definición simple de each
método en Array
podría ser algo como:
class Array
def each
for i in self
yield(i) # If a block has been passed, control will be passed here.
end
end
end
Entonces puedes invocar esto así:
# Add five to each element.
[1, 2, 3, 4].each{ |e| puts e + 5 }
> [6, 7, 8, 9]
Python tiene funciones / cierres / lambdas anónimas, pero no tiene bloques ya que le falta algo del azúcar sintáctico útil. Sin embargo, hay al menos una forma de obtenerlo de manera ad hoc. Ver, por ejemplo, here .
Un poco más en el lado de la infraestructura:
Python tiene una integración mucho mejor con C ++ (a través de elementos como Boost.Python , SIP y Py++ ) que Ruby, donde las opciones parecen ser escribir directamente en contra de la API del intérprete de Ruby (que también se puede hacer con Python, por supuesto, pero en ambos casos, hacerlo es de bajo nivel, tedioso y propenso a errores) o usar SWIG (que, si bien funciona y definitivamente es excelente si desea admitir muchos idiomas, no es tan bueno como Boost.Python o SIP si Usted está buscando específicamente para enlazar C ++).
Python tiene varios entornos de aplicaciones web (Django, Pylons / Turbogears, web.py, probablemente al menos media docena más), mientras que Ruby (efectivamente) tiene uno: Rails. (Existen otros frameworks web de Ruby, pero parece que tienen dificultades para conseguir mucha tracción contra Rails). ¿Es este aspecto bueno o malo? Difícil de decir, y probablemente bastante subjetivo; Puedo imaginar fácilmente los argumentos de que la situación de Python es mejor y que la situación de Ruby es mejor.
Culturalmente, las comunidades de Python y Ruby parecen algo diferentes, pero solo puedo insinuar esto ya que no tengo mucha experiencia interactuando con la comunidad de Ruby. Lo agrego principalmente con la esperanza de que alguien que tenga mucha experiencia con ambos pueda amplificar (o rechazar) esta afirmación.
Algunos otros de:
(Si he malinterpretado algo o alguno de estos ha cambiado en el lado de Ruby desde que se actualizó esa página, alguien puede editarlo ...)
Las cadenas son mutables en Ruby, no en Python (donde las nuevas cadenas se crean mediante "cambios").
Ruby tiene algunas convenciones de casos forzadas, Python no.
Python tiene tanto listas como tuplas (listas inmutables). Ruby tiene matrices correspondientes a las listas de Python, pero ninguna variante inmutable de ellas.
En Python, puedes acceder directamente a los atributos de los objetos. En Ruby, siempre es a través de métodos.
En Ruby, los paréntesis para las llamadas a métodos suelen ser opcionales, pero no en Python.
Ruby tiene acceso público, privado y protegido para imponer el acceso, en lugar de la convención de Python de usar guiones bajos y la manipulación de nombres.
Python tiene herencia múltiple. Ruby tiene "mixins".
Y otro enlace muy relevante:
http://c2.com/cgi/wiki?PythonVsRuby
Lo que, en particular, enlaza con otro bueno de Alex Martelli , quien también ha publicado muchas cosas geniales aquí en SO:
http://groups.google.com/group/comp.lang.python/msg/028422d707512283
Copia descarada / pegada de: Alex Martelli responde en el hilo " ¿Qué es mejor acerca de Ruby que Python? " De la lista de correo comp.lang.python .
18 de agosto de 2003, 10:50 am Erik Max Francis escribió:
"Brandon J. Van Every" escribió:
¿Qué es mejor sobre Ruby que Python? Estoy seguro de que hay algo. ¿Qué es?
¿No tendría mucho más sentido preguntarle esto a la gente Ruby, en lugar de a la gente de Python?
Puede, o no, dependiendo de los propósitos de uno, por ejemplo, si los propósitos incluyen un "estudio sociológico" de la comunidad de Python, es probable que las preguntas a esa comunidad resulten más reveladoras de la información, en lugar de ponerlas en otro lugar. :-).
Personalmente, con mucho gusto aproveché la oportunidad para seguir el tutorial de un día de Ruby de Dave Thomas en el último OSCON. Debajo de una delgada capa de diferencias de sintaxis, encuentro que Ruby y Python son sorprendentemente similares: si estuviera calculando el árbol de expansión mínimo entre casi cualquier conjunto de idiomas, estoy bastante seguro de que Python y Ruby serían las dos primeras hojas en unirse. un nodo intermedio :-).
Claro, en Ruby, me canso de escribir el "final" tonto al final de cada bloque (en lugar de solo unintenting), pero luego evito escribir el ":" igualmente tonto que Python requiere en el inicio de cada bloque, así que eso es casi un lavado :-). Otras diferencias de sintaxis, como ''@foo'' versus ''self.foo'', o el mayor significado del caso en Ruby vs Python, son realmente tan irrelevantes para mí.
Sin duda, otros basan su elección de los lenguajes de programación en esos problemas, y generan los debates más candentes, pero para mí eso es solo un ejemplo de una de las Leyes de Parkinson en acción (la cantidad de debate sobre un tema es inversamente proporcional a la del tema). importancia real).
Edit (por AM 6/19/2010 11:45): esto también se conoce como "pintar el bikeshed" (o, para abreviar, "bikeshedding") - la referencia es, nuevamente, a Northcote Parkinson, quien dio "debates" sobre qué color pintar la malla para bicicletas "como un ejemplo típico de" debates candentes sobre temas triviales ". (fin de edición).
Una diferencia de sintaxis que considero importante, y en favor de Python, pero otras personas sin duda pensarán lo contrario, es "cómo se llama una función que no requiere parámetros". En Python (como en C), para llamar a una función, siempre se aplica el "operador de llamada" - paréntesis finales justo después del objeto al que se llama (dentro de esos paréntesis finales va el argumento que está pasando en la llamada - si no está pasando ningún argumento, entonces los paréntesis están vacíos). Esto deja la mera mención de cualquierObjeto, sin operador involucrado, que significa solo una referencia al objeto, en cualquier contexto, sin casos especiales, excepciones, reglas ad-hoc y similares. En Ruby (como en Pascal), para llamar a una función CON argumentos, usted pasa los argumentos (normalmente entre paréntesis, aunque no siempre es así) - PERO si la función no tiene argumentos, simplemente mencionando la función implícitamente lo llama. Esto puede satisfacer las expectativas de muchas personas (al menos, sin duda, aquellas cuya única experiencia previa de programación fue con Pascal, u otros lenguajes con "llamadas implícitas" similares, como Visual Basic), pero para mí, significa que la mera mención de un objeto puede significar una referencia al objeto, O una llamada al objeto, dependiendo del tipo del objeto, y en aquellos casos en que pueda ''Para obtener una referencia al objeto simplemente mencionándolo, necesitaré usar explícitamente "dame una referencia a esto, ¡NO lo llames!" Operadores que no son necesarios de lo contrario. Siento que esto afecta la "primera clase" de las funciones (o métodos, u otros objetos exigibles) y la posibilidad de intercambiar objetos sin problemas. Por lo tanto, para mí, esta diferencia específica de sintaxis es una marca negra seria contra Ruby, pero entiendo por qué los demás dirían lo contrario, a pesar de que no podría estar en desacuerdo con más vehemencia con ellos :-).Por lo tanto, para mí, esta diferencia específica de sintaxis es una marca negra seria contra Ruby, pero entiendo por qué los demás dirían lo contrario, a pesar de que no podría estar en desacuerdo con más vehemencia con ellos :-).Por lo tanto, para mí, esta diferencia específica de sintaxis es una marca negra seria contra Ruby, pero entiendo por qué los demás dirían lo contrario, a pesar de que difícilmente podría estar en desacuerdo con ellos :-).
Debajo de la sintaxis, entramos en algunas diferencias importantes en la semántica elemental, por ejemplo, las cadenas en Ruby son objetos mutables (como en C ++), mientras que en Python no son mutables (como en Java, o creo que C #). Nuevamente, las personas que juzgan principalmente por lo que ya conocen pueden pensar que esto es una ventaja para Ruby (a menos que estén familiarizados con Java o C #, por supuesto :-). Creo que las cadenas inmutables son una excelente idea (y no me sorprende que Java, independientemente, creo que haya reinventado esa idea que ya estaba en Python), aunque tampoco me importaría tener un tipo de "búfer de cadena mutable" (e idealmente uno con una mayor facilidad de uso que los propios "buffers de cadenas" de Java); y no doy este juicio por familiaridad, antes de estudiar Java,Aparte de los lenguajes de programación funcionales donde todosLos datos son inmutables, todos los lenguajes que conocía tenían cadenas mutables. Sin embargo, cuando vi por primera vez la idea de cadenas inmutables en Java (que aprendí mucho antes de aprender Python), inmediatamente me pareció excelente, una muy buena opción para la semántica de referencia de un lenguaje de programación de nivel superior (a diferencia de la semántica de valor que se ajusta mejor a los lenguajes más cercanos a la máquina y más alejados de las aplicaciones, como C) con cadenas como de primera clase, incorporadas (y bastante importantes) ) tipo de datos.
Ruby tiene algunas ventajas en la semántica elemental, por ejemplo, la eliminación de las "listas vs tuplas de Python" es una distinción extremadamente sutil. Pero principalmente la puntuación (como la mantengo, con sencillez una gran ventaja y sutiles, distinciones inteligentes una notable desventaja) es contra Ruby (por ejemplo, con intervalos cerrados y semiabiertos, con las anotaciones a..b y a .. .b [cualquiera quiere afirmar que es obvio cuál es cuál? -)], es una tontería - ¡En mi humilde opinión, por supuesto! Una vez más, las personas que consideran tener muchas cosas similares pero sutilmente diferentes en el núcleo de un lenguaje PLUS, en lugar de MINUS, contarán estas "al revés" de cómo las cuento :-).
No se deje engañar por estas comparaciones para pensar que los dos idiomas son muydiferente, fíjate. No lo son Pero si me piden que compare "capelli d''angelo" con "spaghettini", después de señalar que estos dos tipos de pasta son casi indistinguibles para cualquiera e intercambiables en cualquier plato que desee preparar, inevitablemente tendré para pasar al examen microscópico de cómo las longitudes y los diámetros difieren imperceptiblemente, cómo los extremos de las hebras se afilan en un caso y no en el otro, y así sucesivamente, para tratar de explicar por qué, personalmente, preferiría haber capelli d ''angelo como la pasta en cualquier tipo de caldo, pero preferiría spaghettini como la pasta para acompañar salsas adecuadas para formas de pasta tan largas y delgadas (aceite de oliva, ajo picado, pimientos rojos picados y anchoas finamente molidas,por ejemplo, pero si cortó el ajo y los pimientos en lugar de picarlos, debería elegir el cuerpo de espaguetis más fino en lugar de la evanescencia más fina de los espaguetis, y sería aconsejable que renunciara a los achovies y en su lugar agregue algo de albahaca fresca de primavera [ o incluso - soy un hereje ...! - hojas de menta ligera ...] - en el último momento antes de servir el plato). Vaya, lo siento, muestra que estoy viajando al extranjero y no he tenido pasta por un tiempo, supongo. ¡Pero la analogía sigue siendo bastante buena!muestra que estoy viajando al extranjero y no he tenido pasta por un tiempo, supongo. ¡Pero la analogía sigue siendo bastante buena!muestra que estoy viajando al extranjero y no he tenido pasta por un tiempo, supongo. ¡Pero la analogía sigue siendo bastante buena!
Así que, volviendo a Python y Ruby, llegamos a los dos grandes (en términos de lenguaje apropiado - dejando las bibliotecas y otros elementos auxiliares importantes como herramientas y entornos, cómo incrustar / extender cada idioma, etc., etc.). por ahora, no se aplicarían a todas las IMPLEMENTACIONES de cada idioma, por ejemplo, ¡Jython vs Classic Python son dos implementaciones del lenguaje Python!):
Los iteradores y bloques de código de Ruby frente a los iteradores y generadores de Python;
TOTAL de Ruby, "dinámica dinámica" desenfrenada, incluida la capacidad
de "reabrir" cualquier clase existente, incluidas todas las integradas, y cambiar su comportamiento en tiempo de ejecución - frente a la gran dinamismo pero limitada de Python , que nunca cambia el comportamiento de la existencia Clases incorporadas y sus instancias.Personalmente, considero 1 un lavado (las diferencias son tan profundas que podría ver fácilmente a las personas que odian a cualquiera que se acerque y veneren al otro, pero en MI personal, las ventajas y desventajas son casi iguales); y 2 es un tema crucial: uno que hace que Ruby sea mucho más adecuado para "retoques", PERO Python es más adecuado para su uso en aplicaciones de gran producción. En cierto modo, es divertido, porque ambos idiomas son MUCHO más dinámicos que la mayoría de los otros, que al final la diferencia clave entre ellos de mi punto de vista debería depender de eso, que Ruby "llega a once" en este sentido (la referencia Aquí está a "Spinal Tap", por supuesto). En Ruby, no hay límites para mi creatividad, si decido que todas las comparaciones de cadenas deben ser insensibles a mayúsculas y minúsculas,YO PUEDO HACER ESO! Es decir, puedo alterar dinámicamente la clase de cadena incorporada para que a = "Hola mundo" b = "hola mundo" si a == b imprime "¡igual! / N" de lo contrario imprime "diferente! / N" el final se imprimirá " igual". En Python, NO hay manera de que pueda hacer eso. Para los propósitos de la metaprogramación, la implementación de marcos experimentales y similares, esta sorprendente capacidad dinámica de Ruby es extremadamenteatractivo. PERO, si estamos hablando de aplicaciones de gran tamaño, desarrolladas por muchas personas y mantenidas por muchas más, incluyendo todo tipo de bibliotecas de diversas fuentes, y que necesitan entrar en producción en sitios de clientes ... bueno, no QUIERO Un lenguaje que es MUY dinámico, muchas gracias. Detesto la idea de que alguna biblioteca rompa, involuntariamente, otra no relacionada que se basa en que esas cadenas sean diferentes. Ese es el tipo de "canal" profundo y profundamente oculto, entre piezas de código que SE VENCIAN separadas y DEBEN estar separadas, que deletrean la muerte. Programación a gran escala. Al permitir que cualquier módulo afecte el comportamiento de cualquier otro "encubierto", la capacidad de mutar la semántica de los tipos incorporados es solo una MALA idea para la programación de aplicaciones de producción, al igual que es genial para retoques.
Si tuviera que usar Ruby para una aplicación tan grande, trataría de basarme en restricciones de estilo de codificación, muchas pruebas (para ser ejecutadas cada vez que CUALQUIERA cambie, incluso lo que debería ser totalmente no relacionado ...), y cosas por el estilo, para prohibir el uso de esta característica de lenguaje. Pero NO tener la característica en primer lugar es aún mejor, en mi opinión, al igual que Python en sí mismo sería un lenguaje aún mejor para la programación de aplicaciones si un cierto número de incorporaciones pudieran ser "clavadas", por lo que SABÍA que , por ejemplo, len ("ciao") es 4 (en lugar de tener que preocuparse subliminalmente de si alguien ha cambiado el enlace del nombre ''len'' en el módulo incorporado ...). Espero que con el tiempo Python "apunte" sus integraciones.
Pero el problema es menor, ya que volver a encuadernar las incorporaciones es una práctica poco habitual y poco habitual en Python. En Ruby, me parece importante, al igual que las instalaciones de macros demasiado potentes de otros idiomas (como, por ejemplo, Dylan) presentan riesgos similares en mi opinión (espero que Python nunca obtenga un sistema de macros tan poderoso, no importa el encanto de "dejar que las personas definan sus propios lenguajes específicos de dominio incrustados en el lenguaje mismo", IMHO, perjudicaría la maravillosa utilidad de Python para la programación de aplicaciones, al presentar una "molestia atractiva" para el posible retorcedor que Se esconde en el corazón de cada programador ...).
Alex
En esta etapa, Python aún tiene mejor soporte para Unicode
Mi python está oxidado, por lo que algunos de estos pueden estar en python y no recuerdo / nunca aprendí, pero aquí están los primeros en los que pensé
Espacio en blanco
Ruby maneja los espacios en blanco completamente diferentes. Para empezar, no necesitas sangrar nada (lo que significa que no importa si usas 4 espacios o 1 pestaña). También hace la continuación de la línea inteligente, por lo que lo siguiente es válido:
def foo(bar,
cow)
Básicamente, si terminas con un operador, se da cuenta de lo que está pasando.
Mixins
Ruby tiene mixins que pueden extender instancias en lugar de clases completas:
module Humor
def tickle
"hee, hee!"
end
end
a = "Grouchy"
a.extend Humor
a.tickle » "hee, hee!"
Enums
No estoy seguro si esto es lo mismo que los generadores, pero a partir de Ruby 1.9 ruby como enums, entonces
>> enum = (1..4).to_enum
=> #<Enumerator:0x1344a8>
Referencia: http://blog.nuclearsquid.com/writings/ruby-1-9-what-s-new-what-s-changed
"Argumentos de palabras clave"
Ambos elementos enumerados allí son compatibles con Ruby, aunque no puedes omitir valores predeterminados como ese. Puedes ir en orden
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
Tenga en cuenta que c = 5 asigna realmente a la variable c en el alcance de la llamada el valor 5, y establece el parámetro b el valor 5.
o puedes hacerlo con hashes, que abordan el segundo problema
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
Referencia: La Guía del Programa Pragmático para Ruby
No estoy seguro de esto, así que primero lo agrego como respuesta.
Python trata los métodos no unidos como funciones.
Eso significa que puedes llamar a un método como theobject.themethod()
o por TheClass.themethod(anobject)
.
Edición: Aunque la diferencia entre los métodos y las funciones es pequeña en Python y no existe en Python 3, tampoco existe en Ruby, simplemente porque Ruby no tiene funciones. Cuando define funciones, en realidad está definiendo métodos en Object.
Pero aún no puede tomar el método de una clase y llamarlo como una función, tendría que volver a vincularlo con el objeto al que desea llamar, lo cual es mucho más difícil.
Python tiene cadenas de documentación y ruby no ... O si no, no son accesibles tan fácilmente como en Python.
PD. Si me equivoco, bonito por favor, deja un ejemplo? Tengo una solución alternativa que podría dividir fácilmente en las clases con bastante facilidad, pero me gustaría tener una cadena de documentación como una característica de "forma nativa".
Ruby tiene incrustada documentación:
=begin
You could use rdoc to generate man pages from this documentation
=end
Ruby tiene sigilos y twigils, Python no.
Edit : Y una cosa muy importante que olvidé (después de todo, la anterior fue solo un poco de fuego :-p):
Python tiene un compilador JIT ( Psyco ), un lenguaje de nivel inferior para escribir código más rápido ( Pyrex ) y la capacidad de agregar código C ++ en línea ( Weave ).
python ha nombrado argumentos opcionales
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 solo ha posicionado los argumentos porque b = 2 en la declaración de función es una afectación que siempre se agrega.
La sintaxis no es una cosa menor, tiene un impacto directo en cómo pensamos. También tiene un efecto directo en las reglas que creamos para los sistemas que utilizamos. Como ejemplo, tenemos el orden de las operaciones debido a la forma en que escribimos ecuaciones u oraciones matemáticas. La notación estándar para las matemáticas permite que las personas lo lean de varias maneras y lleguen a diferentes respuestas dada la misma ecuación. Si hubiéramos usado el prefijo o la notación de postfijo, habríamos creado reglas para distinguir cuáles eran los números a manipular en lugar de tener solo reglas para el orden en el cual calcular los valores.
La notación estándar deja en claro de qué números estamos hablando al hacer el orden en el que se calculan de forma ambigua. La notación de prefijo y postfijo establece el orden en el que se debe calcular el plano al mismo tiempo que los números son ambiguos. Python ya tendría lambdas multilínea si no fuera por las dificultades causadas por el espacio en blanco sintáctico. (Existen propuestas para eliminar este tipo de cosas sin agregar necesariamente delimitadores de bloques explícitos).
Me resulta más fácil escribir condiciones donde quiero que ocurra algo si una condición es falsa y mucho más fácil de escribir con la declaración menos en Ruby que la construcción semántica equivalente "si no" en Ruby u otros idiomas, por ejemplo. Si la mayoría de los idiomas que usan las personas hoy en día tienen el mismo poder, ¿cómo puede la sintaxis de cada idioma ser considerada algo trivial? Después de características específicas como bloques, mecanismos de herencia, etc., la sintaxis es la parte más importante de un lenguaje, apenas una cosa superficial.
Lo que es superficial son las cualidades estéticas de la belleza que atribuimos a la sintaxis. La estética no tiene nada que ver con cómo funciona nuestra cognición, la sintaxis sí.
Me gustaría mencionar la API del descriptor de Python que permite personalizar una "comunicación" de objeto a atributo. También es digno de mención que, en Python, uno es libre de implementar un protocolo alternativo anulando el valor predeterminado dado a través de la implementación predeterminada del __getattribute__
método. Permítanme darles más detalles sobre lo anterior. Los descriptores son clases regulares con __get__
, __set__
y / o __delete__
métodos. Cuando el intérprete encuentra algo así anObj.anAttr
, se realiza lo siguiente:
-
__getattribute__
anObj
se invoca metodo de -
__getattribute__
recupera un objetoAttr de la clase dict - Se comprueba si el objeto abAttr tiene
__get__
,__set__
o__delete__
los objetos no desembolsadas - el contexto (es decir, el objeto o la clase que llama, y el valor, en lugar del último, si tenemos un configurador) se pasa al objeto que se puede llamar
- Se devuelve el resultado.
Como se mencionó, este es el comportamiento por defecto. Uno es libre de cambiar el protocolo re-implementándolo __getattribute__
.
Esta técnica es mucho más poderosa que los decoradores.
Otra diferencia en lambdas entre Python y Ruby se demuestra por el problema del Generador de acumulador de Paul Graham . Reimpreso aquí:
Escriba una función foo que tome un número n y devuelva una función que tome un número i, y devuelva n incrementado en i. Nota: (a) ese es el número, no el entero, (b) se incrementa, no más.
En Ruby, puedes hacer esto:
def foo(n)
lambda {|i| n += i }
end
En Python, crearías un objeto para mantener el estado de n:
class foo(object):
def __init__(self, n):
self.n = n
def __call__(self, i):
self.n += i
return self.n
Algunas personas pueden preferir que el enfoque explícito de Python sea más claro conceptualmente, incluso si es un poco más detallado. Usted almacena el estado como lo hace para cualquier otra cosa. Solo necesitas envolver tu cabeza en torno a la idea de objetos que se pueden llamar. Pero independientemente del enfoque estético que se prefiera, muestra un aspecto en el que las lambdas de rubí son construcciones más poderosas que las de Python.
Puede tener código en la definición de clase tanto en Ruby como en Python. Sin embargo, en Ruby tienes una referencia a la clase (self). En Python no tienes una referencia a la clase, ya que la clase aún no está definida.
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.
Ruby ha incorporado soporte de continuación usando callcc
.
Por lo tanto puedes implementar cosas geniales como el amb-operator
Ruby tiene un bucle línea por línea sobre los archivos de entrada (el distintivo ''-n'') desde la línea de comandos para que se pueda utilizar como AWK. Este Ruby de una sola línea:
ruby -ne ''END {puts $.}''
contará líneas como el AWK de una sola línea:
awk ''END{print NR}''
Ruby obtiene esta característica a través de Perl, que lo tomó de AWK como una forma de conseguir administradores de sistemas con Perl sin tener que cambiar la forma en que hacen las cosas.
Sorprendido de no ver nada mencionado del mecanismo de "falta el método" de ruby. Daría ejemplos de los métodos find_by _... en Rails, como ejemplo del poder de esa característica de lenguaje. Mi conjetura es que algo similar podría implementarse en Python, pero que yo sepa no existe de forma nativa.