Há muitas discussões sobre Python x Ruby, e todas as considero completamente inúteis, porque todas elas se voltam para o motivo pelo qual o recurso X é péssimo na linguagem Y ou que afirma que a linguagem Y não possui X, embora, na verdade, exista. Também sei exatamente por que prefiro o Python, mas isso também é subjetivo e não ajudaria ninguém a escolher, pois eles podem não ter o mesmo gosto em desenvolvimento que eu.
Seria, portanto, interessante listar as diferenças objetivamente. Portanto, nenhuma "lambda do Python é uma merda". Em vez disso, explique o que as lambdas de Ruby podem fazer e as de Python. Sem subjetividade. Código de exemplo é bom!
Não tenha várias diferenças em uma resposta, por favor. E vote nas que você sabe que estão corretas e as que você conhece estão incorretas (ou são subjetivas). Além disso, as diferenças na sintaxe não são interessantes. Sabemos que Python faz com indentação o que Ruby faz com colchetes e termina, e que @ é chamado self em Python.
ATUALIZAÇÃO: Agora é um wiki da comunidade, para que possamos adicionar grandes diferenças aqui.
Ruby tem uma referência de classe no corpo da classe
No Ruby, você tem uma referência à classe (auto) já no corpo da classe. No Python, você não tem uma referência à classe até que a construção da classe seja concluída.
Um exemplo:
class Kaka
puts self
end
self neste caso é a classe e esse código imprimiria "Kaka". Não há como imprimir o nome da classe ou, de outras formas, acessar a classe a partir do corpo da definição de classe no Python (fora das definições de método).
Todas as classes são mutáveis em Ruby
Isso permite que você desenvolva extensões para classes principais. Aqui está um exemplo de uma extensão de trilhos:
class String
def starts_with?(other)
head = self[0, other.length]
head == other
end
end
Python (imagine que não havia ''.startswith
método):
def starts_with(s, prefix):
return s[:len(prefix)] == prefix
Você pode usá-lo em qualquer sequência (não apenas em seqüências de caracteres). Para usá-lo, você deve importá-lo explicitamente , por exemplo from some_module import starts_with
,.
Ruby possui recursos de script semelhantes ao Perl
O Ruby possui regexps de primeira classe, variáveis-$, o loop de entrada de linha por linha do awk / perl e outros recursos que o tornam mais adequado para escrever pequenos scripts de shell que movem arquivos de texto ou agem como código de cola para outros programas.
Ruby tem continuações de primeira classe
Graças à declaração callcc. No Python, você pode criar continuações usando várias técnicas, mas não há suporte incorporado à linguagem.
Ruby tem blocos
Com a instrução "do", você pode criar uma função anônima de várias linhas no Ruby, que será passada como argumento para o método na frente do do e chamada a partir daí. Em Python, você faria isso passando um método ou com geradores.
Rubi:
amethod { |here|
many=lines+of+code
goes(here)
}
Python (blocos Ruby correspondem a diferentes construções em 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
Curiosamente, a declaração de conveniência no Ruby para chamar um bloco é chamada "yield", que no Python criará um gerador.
Rubi:
def themethod
yield 5
end
themethod do |foo|
puts foo
end
Pitão:
def themethod():
yield 5
for foo in themethod():
print foo
Embora os princípios sejam diferentes, o resultado é surpreendentemente semelhante.
O Ruby suporta programação de estilo funcional (semelhante a um tubo) com mais facilidade
myList.map(&:description).reject(&:empty?).join("\n")
Pitão:
descriptions = (f.description() for f in mylist)
"\n".join(filter(len, descriptions))
O Python possui geradores internos (que são usados como blocos Ruby, conforme observado acima)
Python tem suporte para geradores na linguagem. No Ruby 1.8, você pode usar o módulo gerador, que usa continuações para criar um gerador a partir de um bloco. Ou você pode simplesmente usar um bloco / proc / lambda! Além disso, no Ruby 1.9, as fibras são e podem ser usadas como geradores, e a classe Enumerator é um gerador interno .
docs.python.org tem este exemplo de gerador:
def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
Compare isso com os exemplos de blocos acima.
Python possui manipulação de espaço de nome flexível
No Ruby, quando você importa um arquivo require
, todas as coisas definidas nesse arquivo acabam no seu espaço de nome global. Isso causa poluição no espaço para nome. A solução para isso são os módulos Rubys. Mas se você criar um espaço para nome com um módulo, precisará usá-lo para acessar as classes contidas.
No Python, o arquivo é um módulo e você pode importar seus nomes contidos from themodule import *
, poluindo o espaço para nome, se desejar. Mas você também pode importar apenas os nomes selecionados from themodule import aname, another
ou simplesmente import themodule
acessar os nomes com themodule.aname
. Se você deseja mais níveis no seu espaço para nome, pode ter pacotes, que são diretórios com módulos e um __init__.py
arquivo.
Python tem docstrings
Docstrings são strings anexadas a módulos, funções e métodos e podem ser introspectivas em tempo de execução. Isso ajuda a criar itens como o comando help e a documentação automática.
def frobnicate(bar):
"""frobnicate takes a bar and frobnicates it
>>> bar = Bar()
>>> bar.is_frobnicated()
False
>>> frobnicate(bar)
>>> bar.is_frobnicated()
True
"""
Os equivalentes do Ruby são semelhantes aos javadocs e localizados acima do método, e não dentro dele. Eles podem ser recuperados em tempo de execução a partir dos arquivos usando o Método 1.9 do código # source_location exemplo use
Python tem herança múltipla
O Ruby não ("de propósito" - consulte o site do Ruby, veja aqui como é feito no Ruby ). Ele reutiliza o conceito de módulo como um tipo de classes abstratas.
Python tem compreensão de lista / dict
Pitão:
res = [x*x for x in range(1, 10)]
Rubi:
res = (0..9).map { |x| x * x }
Pitão:
>>> (x*x for x in range(10))
<generator object <genexpr> at 0xb7c1ccd4>
>>> list(_)
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Rubi:
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'}
Rubi:
>> Hash[{1=>2, 3=>4}.map{|x,y| [x,(y*y).to_s]}]
=> {1=>"4", 3=>"16"}
Python tem decoradores
Coisas semelhantes aos decoradores também podem ser criadas no Ruby, e também se pode argumentar que elas não são tão necessárias quanto no Python.
Diferenças de sintaxe
Ruby requer "end" ou "}" para fechar todos os seus escopos, enquanto o Python usa apenas espaço em branco. Houve tentativas recentes em Ruby de permitir apenas recuo de espaço em branco http://github.com/michaeledgar/seamless