O que Ruby tem que Python não tem, e vice-versa?

263

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 ''.startswithmé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, anotherou simplesmente import themoduleacessar 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__.pyarquivo.

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

Lennart Regebro
fonte
2
Com relação à herança múltipla, dizer apenas "Ruby does not" é falso. Não consigo pensar em nada que você possa fazer em Python com herança múltipla que você não pode fazer em ruby ​​com modules / "herança de mixin". (É ainda discutível que inclui módulos simplesmente é herança múltipla.)
Logan Capaldo
2
Que você possa fazer a mesma coisa de outra maneira é um argumento que não se sustenta. Você pode fazer tudo aqui de outra maneira. E como os módulos não são classes, não é herança múltipla. Você pode contribuir com exemplos de código de como isso é feito na herança múltipla Pythons vs com módulos Rubys.
Lennart Regebro 11/07/2009
3
Módulos não são Classes, mas Classes são Módulos. % ruby ​​-e 'p Classe <Módulo' true
Logan Capaldo
8
-1 Infelizmente, esta questão perde seu objetivo e a maioria das supostas diferenças não são diferenças e a desinformação é abundante!
viés
2
As inclusões do módulo são, de fato, herança múltipla, não apenas no conceito, mas na implementação real no interpretador Ruby. Quando um módulo Ruby é incluído, ele é injetado na cadeia de herança exatamente da mesma maneira que as superclasses. A resolução do método é a mesma. No Ruby, vários módulos incluem herança múltipla. Quem quer contestar isso como semanticamente "não é a mesma coisa" como herança múltipla está apenas sendo pedante. Qual o sentido de algo não ser a "mesma coisa" se o efeito é idêntico e facilmente alcançado? Uma distinção sem diferença.
Dave Sims

Respostas:

34

Ruby tem os conceitos de blocos , que são essencialmente açúcar sintático em torno de uma seção do código; eles são uma maneira de criar fechamentos e passá-los para outro método que pode ou não usar o bloco. Um bloco pode ser chamado posteriormente através de uma yieldinstrução.

Por exemplo, uma definição simples de um eachmétodo Arraypode 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  

Então você pode invocar isso assim:

# Add five to each element.
[1, 2, 3, 4].each{ |e| puts e + 5 }
> [6, 7, 8, 9]

O Python possui funções / closures / lambdas anônimas, mas não possui blocos porque está faltando um pouco do açúcar sintático útil. No entanto, há pelo menos uma maneira de obtê-lo de maneira ad-hoc. Veja, por exemplo, aqui .

John Feminella
fonte
6
@Lennart: além de seu exemplo ser horrível, é sintaticamente errado também.
2
@ unbeknow: A, certo. Mas se isso tivesse sido uma função em vez de uma impressão, teria funcionado. No python 3, isso funciona: [print (e + 5) para e em [1,2,3,4]] E quando se trata de horribilidade, acho que o código ruby ​​acima é horrível, então isso é claramente subjetivo e, portanto, não é um parte desta pergunta. @ John Não estou dizendo que é equivalente, estou dizendo que não é óbvio qual é a diferença do seu exemplo. @ Bastien, não, mas o fato de você poder fazer coisas semelhantes não significa que elas são iguais. As diferenças aqui devem ser listadas, mesmo que haja outras maneiras de fazê-lo.
Lennart Regebro 11/07/2009
22
Eu sou um programador Python. Gostaria de ver um exemplo de como os blocos Ruby ajudam você a escrever algo mais conciso ou mais bonito do que com o Python, porque não possui blocos. Seu exemplo pode ser escrito: para i em [1, 2, 3, 4]: print (i + 5). Ele não usa blocos, mas é conciso e bonito, bem como o rubi, cada exemplo.
Manuel Ceron
10
@Manuel, procs são úteis para anexar functores a estruturas de dados não triviais (árvores, gráficos ...) que não podem ser 'executadas em loop' e, portanto, requerem iteradores especiais para serem transversais. Os blocos, que são procs anônimos, permitem implementar o functor em uma expressão (vs. definir e implementar) que acelera drasticamente o processo de codificação e esclarece a intenção. Por exemplo, se você estivesse criando uma estrutura de dados de gráfico, poderia definir um iterador 'each' e depois misturar Enumerable, que instantaneamente lhe daria acesso a dezenas de iteradores (classificar, todos ?, qualquer ?, grep). Agora você chama um bloco ...
polarização
4
@RommeDeSerieux, porque precisa de um nome no idioma! Além disso, é um objeto de função, não uma função. Vejamos o Ruby Docs: "Os objetos Proc são blocos de código que foram vinculados a um conjunto de variáveis ​​locais", portanto, um Proc anônimo é apenas o bloco e certamente não é apenas uma função!
viés
28

Exemplo de Python

Funções são variáveis ​​de primeira classe no Python. Você pode declarar uma função, passá-la como um objeto e substituí-la:

def func(): print "hello"
def another_func(f): f()
another_func(func)

def func2(): print "goodbye"
func = func2

Esse é um recurso fundamental das linguagens de script modernas. JavaScript e Lua também fazem isso. Ruby não trata as funções dessa maneira; nomear uma função chama isso.

Obviamente, existem maneiras de fazer essas coisas no Ruby, mas elas não são operações de primeira classe. Por exemplo, você pode agrupar uma função com Proc.new para tratá-la como uma variável - mas não será mais uma função; é um objeto com um método "call".

As funções do Ruby não são objetos de primeira classe

Funções Ruby não são objetos de primeira classe. As funções devem estar envolvidas em um objeto para distribuí-las; o objeto resultante não pode ser tratado como uma função. As funções não podem ser atribuídas de maneira de primeira classe; em vez disso, uma função em seu objeto contêiner deve ser chamada para modificá-los.

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!"    
viés
fonte
8
Você está muito confuso. Objetos de primeira classe são atribuídos por atribuição:, x = ynão por chamada self.class.send(:define_method, :func, method(:func2)). Seu "contra-exemplo" mostra como as funções de Ruby não são de primeira classe. Se você não concordar, fique à vontade para postar sua própria resposta; Não coloque sua confusão na minha.
Glenn Maynard
7
Coisas definidas por def ... endem ruby ​​não são funções. Eles são métodos (da maneira que você os definiu Kernel). Os métodos podem ser desvinculados (usando o #methodmétodo), que são objetos. A coisa mais próxima que o ruby ​​tem das funções são Procinstâncias, que também são objetos e podem ser passadas ou invocadas. Ele também possui uma sintaxe especial para passar um único retorno Procde chamada para um método, como John Feminella discute em sua resposta .
Junção
4
@ Glenn: Eu entendo o que você está dizendo, mas gostaria de dizer que as funções de redefinição de Ruby - métodos são um conceito semântico separado. Se você deseja jogar o jogo de definição, o código mais imperativo são procedimentos, não funções. Não estou tentando ser difícil, mas acredito que definições e exatidão são importantes. Concordo que manipular um UnboundMethodpode ser uma PITA, também.
rampion
5
@ Glenn: A beleza está nos olhos de quem vê. No entanto, os métodos são objetos de primeira classe, cumprindo a definição (neste caso, estou me referindo à definição da Wikipedia). Talvez você tenha alguma outra definição de primeira classe? Eles precisam de um cartão de passageiro frequente Platinum para obter a primeira classe?
viés
4
@ Glenn Confira a seção SO FAQ "Outras pessoas podem editar minhas coisas ?!" - este é um Wiki da comunidade.
viés
26

Em última análise, todas as respostas serão subjetivas em algum nível, e as respostas postadas até agora provam que você não pode apontar para nenhum recurso que não seja viável no outro idioma de uma maneira igualmente agradável (se não semelhante) , pois os dois idiomas são muito concisos e expressivos.

Eu gosto da sintaxe do Python. No entanto, você precisa se aprofundar um pouco mais que a sintaxe para encontrar a verdadeira beleza do Ruby. Há uma beleza zen na consistência de Ruby. Embora nenhum exemplo trivial possa explicar isso completamente, tentarei criar um aqui apenas para explicar o que quero dizer.

Inverta as palavras nesta sequência:

sentence = "backwards is sentence This"

Quando você pensa em como faria, faria o seguinte:

  1. Divida a frase em palavras
  2. Inverta as palavras
  3. Junte as palavras novamente em uma sequência

Em Ruby, você faria o seguinte:

sentence.split.reverse.join ' '

Exatamente quando você pensa sobre isso, na mesma sequência, uma chamada de método após a outra.

Em python, seria mais parecido com isto:

" ".join(reversed(sentence.split()))

Não é difícil de entender, mas não tem o mesmo fluxo. O sujeito (frase) está enterrado no meio. As operações são uma mistura de funções e métodos de objeto. Este é um exemplo trivial, mas descobrimos muitos exemplos diferentes ao realmente trabalhar e entender o Ruby, especialmente em tarefas não triviais.

Mark Thomas
fonte
1
Concordo. Ruby parece fluir naturalmente quando eu o escrevo, então "zenlike" é um bom termo.
the Tin Man
18

Python tem uma mentalidade de "somos todos adultos aqui". Assim, você descobrirá que Ruby tem coisas como constantes, enquanto Python não (embora as constantes de Ruby apenas gerem um aviso). O modo de pensar do Python é que, se você deseja tornar algo constante, deve colocar os nomes das variáveis ​​em maiúsculas e não alterá-los.

Por exemplo, Ruby:

>> PI = 3.14
=> 3.14
>> PI += 1
(irb):2: warning: already initialized constant PI
=> 4.14

Pitão:

>>> PI = 3.14
>>> PI += 1
>>> PI
4.1400000000000006
Jason Baker
fonte
19
Ha .. isso me lembra que pelo menos no python 2. *, você conseguiu fazer "True, False = False, True" ... acredito que eles corrigiram corretamente isso no python 3.0 ... isso é algo que você deve ser impedido de fazer.
Tom
11
Pessoalmente, gosto de diretrizes rígidas impostas pelo idioma, pois isso torna todo o código escrito nesse idioma consistente. Ele obriga você a seguir as orientações, e os desenvolvedores ler o seu código pode dizer em poucas palavras o que é o quê. Enquanto a maioria dos codificadores Python usa o mesmo "estilo" geral, eu vi algumas inconsistências bastante grandes que não seriam possíveis no Ruby.
Sasha Chedygov
8
@ viés - Eu não sei por que você está me votando. Esta resposta não concorda ou discorda da maneira python de fazer as coisas. É apenas uma declaração de fato.
21330 Jason Baker
13
@ Jason "somos todos adultos aqui" é uma afirmação de um fato? Eu gostaria de chamar isso de uma opinião envolvida em um recurso, daí o voto negativo.
viés
7
@ viés - Dizer "somos todos adultos aqui" não era para ser um pouco. É um lema não oficial Python, que eu acredito que é melhor explicado aqui: mail.python.org/pipermail/tutor/2003-October/025932.html
Evan Porter
18

Você pode importar apenas funções específicas de um módulo no Python. No Ruby, você importa toda a lista de métodos. Você pode "não importar" eles no Ruby, mas não é disso que se trata.

EDITAR:

vamos pegar este módulo Ruby:


module Whatever
  def method1
  end

  def method2
  end
end

se você incluí-lo no seu código:


include Whatever

você verá que ambos method1 e method2 foram adicionados ao seu namespace. Você não pode importar apenas o método1 . Você importa os dois ou não os importa. No Python, você pode importar apenas os métodos de sua escolha. Se isso tivesse um nome, talvez fosse chamado de importação seletiva?

Tempus
fonte
2
Oh, certo! Python gosta de namespaces. Não é esse o caso em Ruby? Você não está import bla; bla.foo()em Ruby?
Lennart Regebro 11/07/2009
2
Você pode importar apenas a função a, nem todas as funções internas. Se, por exemplo, você incluir um módulo Ruby que declara 3 funções não estáticas, todas elas serão incluídas no seu espaço para nome. Em python, você teria que escrever a partir do módulo import *.
Geo
6
Isso não leva a muita confusão de espaço para nome?
Lennart Regebro
1
Eu acho que sim. Isso é o que eu odeio nos módulos Ruby.
Geo
8
Ruby realmente não tem um sistema de módulos no mesmo sentido que python. Exigir funciona basicamente como inclusão de texto com algumas verificações para inclusão de dupilicato. Você pode (ab) usar módulos como espaços para nome, mas modulena verdade é um pouco impróprio. Os módulos são basicamente aulas sans o new, allocatemétodos. Eles funcionam melhor como uma maneira de compartilhar código por classe / objeto, não como mecanismo para particionar bibliotecas ou para compartilhar código entre programas.
Logan Capaldo
16

No site da Ruby :

Similaridades Tal como acontece com Python, em Ruby, ...

  • Há um prompt interativo (chamado irb).
  • Você pode ler documentos na linha de comando (com o comando ri em vez de pydoc).
  • Não há terminadores de linha especiais (exceto a nova linha usual).
  • Literais de strings podem abranger várias linhas, como strings de aspas triplas do Python.
  • Parênteses são para listas e parênteses são para dictos (que, em Ruby, são chamados de "hashes").
  • Matrizes funcionam da mesma maneira (adicioná-las forma uma matriz longa, mas a composição dessa forma a3 = [ a1, a2 ]fornece uma matriz de matrizes).
  • Os objetos são digitados forte e dinamicamente.
  • Tudo é um objeto, e variáveis ​​são apenas referências a objetos.
  • Embora as palavras-chave sejam um pouco diferentes, as exceções funcionam da mesma maneira.
  • Você possui ferramentas de documentos incorporadas (o Ruby é chamado rdoc).

Diferenças Ao contrário do Python, no Ruby, ...

  • Strings são mutáveis.
  • Você pode criar constantes (variáveis ​​cujo valor você não pretende alterar).
  • Existem algumas convenções de caso impostas (por exemplo, nomes de classe começam com uma letra maiúscula, variáveis ​​começam com uma letra minúscula).
  • Existe apenas um tipo de contêiner de lista (uma matriz) e é mutável.
  • As strings com aspas duplas permitem sequências de escape (como \ t) e uma sintaxe especial de "substituição de expressão" (que permite inserir os resultados das expressões Ruby diretamente em outras strings, sem ter que "adicionar" + "strings" + "together") . As strings de aspas simples são como as "strings brutas" do Python.
  • Não há aulas de "novo estilo" e "estilo antigo". Apenas um tipo.
  • Você nunca acessa diretamente atributos. Com Ruby, são todas as chamadas de método.
  • Parênteses para chamadas de método geralmente são opcionais.
  • Há público, privado e proteção para impor o acesso, em vez do Python _voluntary_ underscore __convention__.
  • "Mixin's" são usados ​​em vez de herança múltipla.
  • Você pode adicionar ou modificar os métodos de classes internas. Ambas as linguagens permitem abrir e modificar classes a qualquer momento, mas o Python impede a modificação de built-ins - o Ruby não.
  • Você tem verdadeiro e falso em vez de Verdadeiro e Falso (e nada em vez de Nenhum).
  • Quando testado para a verdade, apenas falso e nulo são avaliados como um valor falso. Tudo o resto é verdadeiro (incluindo 0, 0,0, "" e []).
  • É elsif em vez de elif.
  • É exigir em vez de importar. Caso contrário, porém, o uso é o mesmo.
  • Os comentários no estilo usual nas linhas acima das coisas (em vez de nos documentos abaixo deles) são usados ​​para gerar documentos.
  • Existem vários atalhos que, apesar de lhe permitirem lembrar mais, você aprende rapidamente. Eles tendem a tornar o Ruby divertido e muito produtivo.
kruczkowski
fonte
2
"É exigir em vez de importar. Caso contrário, porém, o uso é o mesmo." Parece ser completamente impreciso.
Glenjamin
Também existem conjuntos em Ruby que as pessoas raramente usam, mas são integrados. Então, posso dizer, stuff_in_backpack = Set.new; stuff_in_backpack << "computador"; stuff_in_backpack << "sapatos"; # e o conjunto manterá todos os valores sem garantir a ordem.
zachaysan
12

O que Ruby tem sobre Python são seus recursos de linguagem de script. Linguagem de script nesse contexto que significa ser usada para "código de cola" em scripts de shell e manipulação geral de texto.

Estes são principalmente compartilhados com o Perl. Expressões regulares internas de primeira classe, $ -Variables, opções úteis de linha de comando, como Perl (-a, -e) etc.

Juntamente com sua sintaxe concisa, porém epxressiva, é perfeita para esse tipo de tarefa.

O Python para mim é mais uma linguagem de negócios de tipo dinâmico, muito fácil de aprender e com uma sintaxe pura. Não é tão "legal" quanto Ruby, mas limpo. O que Python tem sobre Ruby para mim é o grande número de ligações para outras bibliotecas. Ligações ao Qt e outras bibliotecas da GUI, muitas bibliotecas de suporte a jogos e and and. Ruby tem muito menos. Embora as ligações muito usadas, por exemplo, os bancos de dados, sejam de boa qualidade, eu achei as bibliotecas de nicho com melhor suporte no Python, mesmo que para a mesma biblioteca também exista uma ligação Ruby.

Então, eu diria que ambas as línguas têm seu uso e é a tarefa que define qual delas usar. Ambos são fáceis de aprender. Eu os uso lado a lado. Ruby para scripts e Python para aplicativos independentes.

haffax
fonte
1
Pergunta de alguém que ainda não conhece Ruby: O que você quer dizer com "$ -Variables"? Você quer dizer variáveis ​​globais? Nesse caso, no Python, uma variável definida em um módulo fora de uma classe ou função é global. Se não - qual é a distinção?
Anon
1
Anon: se você declarar uma variável $ em qualquer lugar do código, ela é global por causa do prefixo. Portanto, não importa onde seja definido, é sempre global e sempre conhecido como tal.
Robert K
8
Não exatamente, na verdade eu quis dizer variáveis ​​predefinidas como $ _, $ 1 etc. Essas são preenchidas automaticamente com valores pelo próprio ruby. $ _ é a última linha lida. $ 1, $ 2 etc. são as correspondências de expressão regular da última correspondência. Veja aqui uma lista completa: zenspider.com/Languages/Ruby/QuickRef.html#17 É basicamente um truque para scripts compactos. Você também pode obter todas as informações por meio de chamadas de API, mas usando variáveis ​​$ é mais conciso. Esse tipo de variável simplesmente não se adequa ao estilo do Python, eles deliberadamente os deixaram de fora.
haffax
Obrigado pelo link zenspider - procurava algo assim para uma rápida (não tutorial) sensação do Ruby.
Anon
12

Eu não acho que "Ruby tem X e Python não, enquanto Python tem Y e Ruby não" é a maneira mais útil de ver isso. São idiomas bastante semelhantes, com muitas habilidades compartilhadas.

Em grande parte, a diferença é o que a linguagem torna elegante e legível. Para usar um exemplo que você criou, ambos teoricamente têm lambdas, mas os programadores de Python tendem a evitá-los, e as construções feitas com eles não parecem tão legíveis ou idiomáticas quanto em Ruby. Portanto, em Python, um bom programador desejará seguir uma rota diferente para resolver o problema do que em Ruby, apenas porque na verdade é a melhor maneira de fazê-lo.

Mandril
fonte
5
Concordo que as lambdas têm escopo limitado e não são úteis em muitos casos. No entanto, não acho justo dizer que os programadores de Python os evitem como uma praga.
Jason Baker
1
Eu concordo que lambdas são usadas frequentemente com Python - como mapear, filtrar, reduzir. A grande diferença parece ser que as lambdas do Python são limitadas a expressões, enquanto os blocos Ruby podem ser multilinhas e envolver instruções. Minha impressão geral do que li sobre Ruby é que esse recurso em particular faz com que os Rubyists adotem a abordagem DSL, enquanto os Pythonistas são mais propensos a criar APIs. Minhas informações sobre Ruby ainda são muito superficiais.
Anon
2
@Lennart: Blocos de múltiplas linhas são usados ​​o tempo todo em Ruby - mais frequentemente do que vejo lambdas usadas no código Python idiomático, na verdade. Para um exemplo comum, consulte info.michael-simons.eu/2007/08/06/rails-respond_to-method .
213 Chuck
1
@Lennart: Não, ele não usa rendimento. (O rendimento de Ruby é completamente diferente do Python de qualquer maneira - ele não retorna um gerador.) Não seria significativo escrever for format in respond_to(). O respond_tométodo não retorna nada significativo - ele simplesmente responde à solicitação HTTP atual. O doin respond_to doé o começo de um bloco. Nesse bloco, falamos com um objeto temporário (rotulado formatneste exemplo) que implementa uma DSL muito básica para responder a uma solicitação HTTP.
213 Chuck
3
Você pode 'misturar Enumerable' contra um gerador e obter instantaneamente 30 iteradores novos e maravilhosos? Você precisa examinar o idioma como um todo antes de entender por que os blocos / Procs são ótimos.
viés
12

Gostaria de sugerir uma variante da pergunta original: "O que Ruby tem que Python não possui e vice-versa?" que admite a resposta decepcionante: "Bem, o que você pode fazer com Ruby ou Python que não pode ser feito no Intercal?" Nada nesse nível, porque Python e Ruby fazem parte da vasta família real sentada no trono de Turing aproximadamente.

Mas e quanto a isso:

O que pode ser feito graciosamente e bem em Python que não pode ser feito em Ruby com tanta beleza e boa engenharia, ou vice-versa?

Isso pode ser muito mais interessante do que a simples comparação de recursos.

Christos Hayward
fonte
um comentário na melhor das hipóteses. ainda meu +1
nawfal
11

O Python possui uma sintaxe explícita e integrada para compreensão de lista e geradores, enquanto no Ruby você usaria blocos de mapa e código.

Comparar

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

para

res = (1..10).map{ |x| x*x }
Dario
fonte
como a compreensão de lista não é um Python simples ? e há uma função de mapa no Python também.
11339 SilentGhost
Mas não há nenhuma sintaxe compreensão de lista em Ruby
Dario
Python: res = map (lambda x: x * x, range (1,10))
GogaRieger 9/09
Python:res=map(2 .__rpow__, range(1,10))
John La Rooy
11

"Variáveis ​​que começam com uma letra maiúscula tornam-se constantes e não podem ser modificadas"

Errado. Eles podem.

Você só recebe um aviso se o fizer.

marca
fonte
2
Se um idioma emitir um aviso para uma operação, é minha opinião que você pode muito bem considerar a operação "não possível". Qualquer outra coisa é loucura.
Porgarmingduod 02/03
11

Um pouco mais no lado da infraestrutura:

  • O Python tem uma integração muito melhor com o C ++ (via Boost.Python , SIP e Py ++ ) do que o Ruby, onde as opções parecem ser escritas diretamente na API do interpretador Ruby (o que você também pode fazer com o Python, é claro, mas em ambos os casos, isso é de baixo nível, tedioso e propenso a erros) ou usa SWIG (que, embora funcione e definitivamente seja ótimo se você deseja oferecer suporte a vários idiomas, não é tão bom quanto o Boost.Python ou SIP se você está procurando especificamente vincular C ++).

  • O Python possui vários ambientes de aplicativos da web (Django, Pylons / Turbogears, web.py, provavelmente pelo menos meia dúzia de outros), enquanto o Ruby (efetivamente) possui um: Rails. (Existem outras estruturas da Web Ruby, mas aparentemente é difícil obter muita tração contra o Rails). Esse aspecto é bom ou ruim? Difícil de dizer, e provavelmente bastante subjetivo; Posso facilmente imaginar argumentos de que a situação do Python é melhor e que a situação do Ruby é melhor.

  • Culturalmente, as comunidades Python e Ruby parecem um pouco diferentes, mas só posso sugerir isso porque não tenho tanta experiência interagindo com a comunidade Ruby. Estou adicionando isso principalmente na esperança de que alguém que tenha muita experiência com ambos possa amplificar (ou rejeitar) essa afirmação.

Jack Lloyd
fonte
7
Seu segundo ponto é, na melhor das hipóteses, mal informado. Você deve começar olhando Rack e Sinatra
Max Ogden
6
Eu observo explicitamente que existem outras pilhas do Rails; Só não acho que alguém esteja realmente usando. Verificar Sinatra e Rack não mudou exatamente essa impressão. Você realmente acha que, digamos, Sinatra (94 perguntas no total), ou Camping (no total 2 perguntas no total), ou qualquer um dos outros, realmente tem uma base de usuários / comunidade real? A maioria deles nem sequer tem usuários da vida real, até onde eu sei. Compare com Django (4K +) ou Rails (7K +), ou mesmo com o web.py.
21411 Jack Lloyd
1
Sinatra é realmente bastante popular para tarefas diferentes e leves devido ao seu DSL. É apenas menos usado porque o MVC da Rail fornece mais. O Rails é realmente construído em rack - é isso que torna possível o Phusion Passenger.
alternativa
11

Copiar / colar descaradamente de: Alex Martelli resposta no tópico " O que há de melhor em Ruby que Python " da lista de discussão comp.lang.python .

18 de agosto de 2003, 10:50 Erik Max Francis escreveu:

"Brandon J. Van Every" escreveu:

O que há de melhor no Ruby que no Python? Tenho certeza de que há algo. O que é isso?

Não faria muito mais sentido perguntar isso ao pessoal do Ruby, em vez do pessoal do Python?

Talvez, ou não, dependendo dos propósitos de alguém - por exemplo, se os propósitos de alguém incluem um "estudo sociológico" da comunidade Python, então, fazer perguntas a essa comunidade provavelmente provará mais informações reveladoras sobre ela do que colocá-las em outros lugares :-).

Pessoalmente, aproveitei a oportunidade para acompanhar o tutorial de Ruby de um dia de Dave Thomas, finalmente no OSCON. Abaixo de um fino verniz de diferenças de sintaxe, acho Ruby e Python incrivelmente semelhantes - se eu estivesse computando a árvore de abrangência mínima entre praticamente qualquer conjunto de idiomas, tenho certeza de que Python e Ruby seriam as duas primeiras folhas a se unir um nó intermediário :-).

Certamente, em Ruby, eu me canso de digitar o "final" bobo no final de cada bloco (em vez de apenas desinteressante) - mas evito digitar o ':' igualmente idiota que Python exige em o início de cada bloco, então isso é quase uma lavagem :-). Outras diferenças de sintaxe como '@foo' versus 'self.foo', ou o significado mais alto de maiúsculas e minúsculas em Ruby vs Python, são realmente tão irrelevantes para mim.

Outros, sem dúvida, baseiam sua escolha de linguagens de programação nesses assuntos e geram os debates mais quentes - mas para mim esse é apenas um exemplo de uma das Leis de Parkinson em ação (o valor do debate sobre um assunto é inversamente proporcional ao da questão). importância real).

Edit (by AM 6/19/2010 11:45): isso também é conhecido como "pintar o bikeshed" (ou, resumidamente, "bikeshedding") - a referência é, novamente, a Northcote Parkinson, que deu "debates sobre que cor pintar o bikeshed "como um exemplo típico de" debates quentes sobre tópicos triviais ". (final de edição).

Uma diferença de sintaxe que eu acho importante, e a favor do Python - mas outras pessoas sem dúvida pensam exatamente o contrário - é "como você chama uma função que não requer parâmetros". No Python (como em C), para chamar uma função, você sempre aplica o "operador de chamada" - parênteses finais logo após o objeto que você está chamando (dentro desses parênteses finais, seguem os argumentos que você está passando na chamada - se você não passa argumentos, então os parênteses estão vazios). Isso deixa a mera menção de qualquerobjeto, sem operador envolvido, como significando apenas uma referência ao objeto - em qualquer contexto, sem casos especiais, exceções, regras ad-hoc e similares. Em Ruby (como em Pascal), para chamar uma função WITH argumentos, você passa os argumentos (normalmente entre parênteses, embora isso não seja invariavelmente o caso) - MAS se a função não aceita argumentos, basta mencionar a função que a chama implicitamente. Isso pode atender às expectativas de muitas pessoas (pelo menos, sem dúvida, aquelas cuja única experiência anterior de programação foi com Pascal, ou outras linguagens com "chamadas implícitas" semelhantes, como o Visual Basic) - mas para mim, isso significa que a simples menção de um objeto pode significar uma referência ao objeto OU uma chamada ao objeto, dependendo do tipo do objeto - e nos casos em que eu puder ' Para obter uma referência ao objeto, basta mencioná-lo. Precisarei usar explícito "dê-me uma referência a isso, NÃO a chame!" operadores que não são necessários de outra forma. Eu sinto que isso afeta a "primeira classe" de funções (ou métodos ou outros objetos que podem ser chamados) e a possibilidade de trocar objetos sem problemas. Portanto, para mim, essa diferença de sintaxe específica é uma séria marca negra contra Ruby - mas eu entendo por que os outros agiriam de outra maneira, mesmo que eu mal pudesse discordar mais veementemente deles :-). de funções (ou métodos ou outros objetos que podem ser chamados) e a possibilidade de trocar objetos sem problemas. Portanto, para mim, essa diferença de sintaxe específica é uma séria marca negra contra Ruby - mas eu entendo por que os outros agiriam de outra maneira, mesmo que eu mal pudesse discordar mais veementemente deles :-). de funções (ou métodos ou outros objetos que podem ser chamados) e a possibilidade de trocar objetos sem problemas. Portanto, para mim, essa diferença de sintaxe específica é uma séria marca negra contra Ruby - mas eu entendo por que os outros agiriam de outra maneira, mesmo que eu mal pudesse discordar mais veementemente deles :-).

Abaixo da sintaxe, encontramos algumas diferenças importantes na semântica elementar - por exemplo, as strings no Ruby são objetos mutáveis ​​(como em C ++), enquanto no Python elas não são mutáveis ​​(como em Java, ou eu acredito em C #). Novamente, as pessoas que julgam principalmente pelo que já estão familiarizadas podem pensar que isso é uma vantagem para Ruby (a menos que estejam familiarizadas com Java ou C #, é claro :-). Eu, acho que seqüências imutáveis ​​são uma excelente ideia (e não estou surpreso que o Java, de forma independente, tenha reinventado a ideia que já estava em Python), embora eu não me importasse de ter um tipo de "buffer de sequência mutável" também (e, idealmente, com melhor facilidade de uso do que os próprios "buffers de string" do Java); e não julgo por causa da familiaridade - antes de estudar Java, todos os dados são imutáveis, todas as linguagens que eu conhecia tinham seqüências de caracteres mutáveis ​​- no entanto, quando vi pela primeira vez a idéia de sequência imutável em Java (que aprendi bem antes de aprender Python), ela imediatamente me pareceu excelente, uma boa opção para a semântica de referência de uma linguagem de programação de nível superior (em oposição à semântica de valores que se encaixa melhor com linguagens mais próximas da máquina e mais distantes dos aplicativos, como C), com strings como primeira classe, embutida (e bastante crucial) tipo de dados.

O Ruby tem algumas vantagens na semântica elementar - por exemplo, a remoção da distinção "sutil versus simples" do Python. Mas, principalmente, a pontuação (como eu a mantenho, com simplicidade, uma grande vantagem e sutil, distinções inteligentes e um notável menos) é contra Ruby (por exemplo, tendo intervalos fechados e semiabertos, com as anotações a..b e a .. .b [alguém quer afirmar que é óbvio qual é qual? ​​-)], é bobagem - IMHO, é claro!). Mais uma vez, as pessoas que consideram ter muitas coisas semelhantes, mas sutilmente diferentes, no núcleo de uma linguagem, um PLUS, em vez de um MINUS, obviamente contará essas coisas "ao contrário" da maneira como as conto :-).

Não se deixe enganar por essas comparações, pensando que as duas línguas são muitodiferente, veja bem. Eles não são. Mas se me pedem para comparar "capelli d'angelo" com "spaghettini", depois de apontar que esses dois tipos de macarrão são praticamente indistinguíveis para qualquer pessoa e intercambiáveis ​​em qualquer prato que você queira preparar, eu inevitavelmente teria para examinar microscopicamente como os comprimentos e diâmetros diferem imperceptivelmente, como as extremidades dos fios são afuniladas em um caso e não no outro, e assim por diante - para tentar explicar por que eu, pessoalmente, preferiria capilar. «angelo como macarrão em qualquer tipo de caldo, mas prefere espaguete como macarrão a molhos adequados para formas tão longas e finas (azeite, alho picado, pimentão picado e anchovas finamente moídas, por exemplo - mas se você cortou o alho e o pimentão em vez de picá-los, deve escolher o corpo mais saudável do espaguete em vez da mais fina evanescência do espaguete, e é recomendável renunciar aos achovies e adicionar um pouco de manjericão fresco [ ou até - eu sou um herege ...! - folhas de hortelã leve ...] - no último momento antes de servir o prato). Opa, desculpe, isso mostra que estou viajando para o exterior e não tenho macarrão há um tempo, eu acho. Mas a analogia ainda é muito boa! ​​-) - folhas de hortelã leve ...] - no último momento antes de servir o prato). Opa, desculpe, isso mostra que estou viajando para o exterior e não tenho macarrão há um tempo, eu acho. Mas a analogia ainda é muito boa! ​​-) - folhas de hortelã leve ...] - no último momento antes de servir o prato). Opa, desculpe, isso mostra que estou viajando para o exterior e não tenho macarrão há um tempo, eu acho. Mas a analogia ainda é muito boa! ​​-)

Então, voltando ao Python e Ruby, chegamos às duas coisas mais importantes (em termos de linguagem propriamente dita - deixando as bibliotecas e outros acessórios importantes, como ferramentas e ambientes, como incorporar / estender cada linguagem etc., etc.) por enquanto - eles não se aplicariam a todas as IMPLEMENTAÇÕES de cada idioma, por exemplo, Jython vs Classic Python sendo duas implementações da linguagem Python!):

  1. Iteradores e blocos de código do Ruby versus iteradores e geradores do Python;

  2. TOTAL do Ruby, "dinamicidade" desenfreada, incluindo a capacidade
    de "reabrir" qualquer classe existente, incluindo todas as incorporadas, e alterar seu comportamento em tempo de execução - versus a dinâmica vasta mas limitada do Python , que nunca muda o comportamento da existente classes internas e suas instâncias.

Pessoalmente, considero 1 uma lavagem (as diferenças são tão profundas que eu poderia facilmente ver as pessoas odiando qualquer abordagem e reverenciando a outra, mas no meu escalas pessoais os prós e contras apenas sobre mesmo para cima); e 2 uma questão crucial - que torna o Ruby muito mais adequado para "mexer", mas o Python é igualmente mais adequado para uso em grandes aplicações de produção. É engraçado, de certa forma, porque os dois idiomas são MUITO mais dinâmicos que a maioria dos outros, que, no final, a principal diferença entre eles do meu ponto de vista deve depender disso - que Ruby "chega às onze" a esse respeito (a referência aqui é para "Spinal Tap", é claro). Em Ruby,EU POSSO FAZER ISSO ! Ou seja, eu posso alterar dinamicamente a classe de string incorporada para que a = "Hello World" b = "olá mundo" se a == b imprima "igual! \ N" else print "diferente! \ N" final imprima " igual". Em python, não há como eu fazer isso. Para fins de metaprogramação, implementação de estruturas experimentais e similares, essa incrível capacidade dinâmica do Ruby é extremamente atraente. MAS - se estamos falando de aplicativos grandes, desenvolvidos por muitas pessoas e mantidos por ainda mais, incluindo todos os tipos de bibliotecas de diversas fontes, e precisando entrar em produção nos sites dos clientes ... bem, eu NÃO QUERO uma linguagem que é MUITO dinâmica, muito obrigado. Eu detesto a própria idéia de uma biblioteca involuntariamente quebrar outras não relacionadas que dependem dessas seqüências de caracteres - esse é o tipo de "canal" profundo e profundamente oculto, entre pedaços de código que parecem separados e DEVEM estar separados, que significa morte em programação em larga escala. Ao permitir que qualquer módulo afete o comportamento de qualquer outro "secretamente", a capacidade de alterar a semântica dos tipos internos é apenas uma má idéia para a programação de aplicativos de produção,

Se eu tivesse que usar o Ruby para um aplicativo tão grande, tentaria confiar em restrições no estilo de codificação, em muitos testes (para ser executado novamente sempre que ALGUMA COISA mudar - mesmo o que não deve ser totalmente relacionado ...), e assim por diante, proibir o uso desse recurso de idioma. Mas NÃO ter o recurso em primeiro lugar é ainda melhor, na minha opinião - assim como o próprio Python seria uma linguagem ainda melhor para a programação de aplicativos se um certo número de built-ins pudesse ser "pregado", então eu sabia que , por exemplo, len ("ciao") é 4 (em vez de precisar se preocupar subliminarmente se alguém alterou a ligação do nome 'len' no módulo builtins ...). Espero que, eventualmente, o Python "prenda" seus built-ins.

Mas o problema é pequeno, uma vez que a religação de embutidos é uma prática bastante obsoleta e rara em Python. Em Ruby, isso me parece importante - assim como as facilidades macro muito poderosas de outras linguagens (como, por exemplo, Dylan), apresentam riscos semelhantes na minha opinião (espero que o Python nunca consiga um sistema macro tão poderoso, não importa o fascínio de "deixar as pessoas definirem suas próprias pequenas linguagens específicas de domínio incorporadas na própria linguagem" - isso IMHO prejudicaria a maravilhosa utilidade do Python para programação de aplicativos, apresentando um "incômodo atraente" para o aspirante a analista que espreita no coração de todo programador ...).

Alex

OscarRyz
fonte
9

Alguns outros de:

http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/to-ruby-from-python/

(Se interpretei algo errado ou algum deles mudou no lado do Ruby desde que a página foi atualizada, alguém pode editar ...)

Strings são mutáveis ​​no Ruby, não no Python (onde novas strings são criadas por "alterações").

O Ruby tem algumas convenções de caso aplicadas, o Python não.

O Python possui listas e tuplas (listas imutáveis). O Ruby possui matrizes correspondentes às listas Python, mas nenhuma variante imutável delas.

No Python, você pode acessar diretamente os atributos do objeto. No Ruby, é sempre via métodos.

Em Ruby, parênteses para chamadas de método geralmente são opcionais, mas não em Python.

Ruby tem público, privado e protegido para impor o acesso, em vez da convenção do Python de usar sublinhados e nomes diferentes.

Python tem herança múltipla. Ruby tem "mixins".

E outro link muito relevante:

http://c2.com/cgi/wiki?PythonVsRuby

O que, em particular, vincula a outro de Alex Martelli , que também está postando muitas coisas excelentes aqui no SO:

http://groups.google.com/group/comp.lang.python/msg/028422d707512283

Anon
fonte
1
Em Ruby você pode simplesmente congelar sua matriz para alterá-lo para algo imutável
user163365
Excelente post por Alex Martelli :)
Skilldrick
8

Não tenho certeza disso, então adiciono-o como resposta primeiro.

Python trata métodos não acoplados como funções

Isso significa que você pode chamar um método como theobject.themethod()ou por TheClass.themethod(anobject).

Edit: Embora a diferença entre métodos e funções seja pequena no Python e inexistente no Python 3, ela também não existe no Ruby, simplesmente porque o Ruby não possui funções. Quando você define funções, na verdade você está definindo métodos no Object.

Mas você ainda não pode pegar o método de uma classe e chamá-lo como uma função, você teria que religá-lo ao objeto que deseja chamar, o que é muito mais difícil.

Lennart Regebro
fonte
Ruby não tem funções. Dito isto, TheClass.instance_method(:themethod).bind(anobject).callseria o equivalente em rubi.
Logan Capaldo
Oh. Portanto, existe algum tipo de classe principal mágica quando você define uma função que não está em uma classe explícita?
Lennart Regebro 11/07/2009
Sim, os métodos definidos no nível superior são métodos privados de Object.
Logan Capaldo
1
FWIW, parece que no Python, funções e métodos são realmente do mesmo tipo, e seu comportamento diferente vem dos descritores: users.rcn.com/python/download/… .
Bastien Léonard
1
Mas se você ligá-lo a um objeto, ele não será vinculado. Duh. :-) E eles são a mesma coisa em Python também. Só que Ruby realmente não tem funções. E isso significa que minha afirmação está correta. Você pode chamar um método não vinculado como se fosse uma função no Python. E isso é realmente útil, ou seja, por exemplo, você pode chamar um método definido em uma classe em um objeto que não possui essa classe, o que às vezes é útil.
Lennart Regebro 16/10/2009
7

Gostaria de mencionar a API do descritor Python que permite personalizar a "comunicação" de objeto a atributo. Também é digno de nota que, em Python, é possível implementar um protocolo alternativo, substituindo o padrão fornecido pela implementação padrão do __getattribute__método. Deixe-me dar mais detalhes sobre o acima mencionado. Descritores são classes regulares com __get__, __set__e / ou __delete__métodos. Quando o intérprete encontra algo parecido anObj.anAttr, é executado o seguinte:

  • __getattribute__método de anObjé invocado
  • __getattribute__ recupera um objeto anAttr da classe dict
  • ele verifica se abAttr objeto tem __get__, __set__ou __delete__objetos que podem ser chamadas
  • o contexto (ou seja, objeto ou classe do chamador e valor, em vez do último, se tivermos setter) é passado para o objeto que pode ser chamado
  • o resultado é retornado.

Como foi mencionado, esse é o comportamento padrão. Um é livre para alterar o protocolo reimplementando __getattribute__.

Essa técnica é muito mais poderosa que os decoradores.

Giorgi
fonte
6

Ruby construiu suporte de continuação usando callcc.

Portanto, você pode implementar coisas legais como o operador amb

Dario
fonte
Eu gostaria de entender callcc. Você pode dar um cenário de aplicação mais mundano do que o Operador Ambíguo de McCarthy, para apreciar seus méritos? Quero dizer algo do mundo real, não aquela coisa descolada do CS ?!
21339 ThomasH
"Funky CS stuff" é real. Tire algum tempo para aprender: intertwingly.net/blog/2005/04/13/Continuations-for-Curmudgeons
Stephen Eilert
6

Nesta fase, o Python ainda possui melhor suporte a unicode

John La Rooy
fonte
5

Python possui docstrings e o ruby ​​não ... Ou, se não tiver, eles não são acessíveis tão facilmente quanto no python.

Ps. Se estiver errado, por favor, deixe um exemplo? Eu tenho uma solução alternativa que eu poderia monkeypatch em classes com bastante facilidade, mas eu gostaria de ter um tipo de recurso de doutrina de "maneira nativa".

rasjani
fonte
3
não possui docstring, mas possui RDoc. Então, sim, não é tão facilmente acessível, mas não 100% oculto.
Omar Qureshi
Ruby não usa docstrings. Faz documentação de uma maneira diferente.
Chuck
1
Omar: Sim, eu sei sobre o rdoc, mas, a afaik, eles não são "tão acessíveis" quanto os documentos do python. Por exemplo, se eu tiver uma classe e desejar gerar a documentação rdoc de dentro da classe, seu trabalho bastante robusto. O que fiz foi gerar uma documentação ri que tento manter up2date e depois buscar essa informação vi ri. Definitivamente não para o mesmo nível que docstrings do Python ..
rasjani
As seqüências de documentos podem ser usadas para fornecer testes. Existe algo assim para Ruby?
Lennart Regebro 11/07/2009
2
Sim, é chamado "Ruby Doctest". No que diz respeito aos documentos, tudo o que realmente importa é que você tenha uma documentação legível em algum lugar que inclua trechos de código testáveis ​​- não faz diferença se está em uma string de documento ou em um comentário.
213 Chuck
5

O Ruby possui um loop linha por linha sobre os arquivos de entrada (o sinalizador '-n') da linha de comando, para que possa ser usado como AWK. Esta linha única de Ruby:

ruby -ne 'END {puts $.}'

contará linhas como o one-liner AWK:

awk 'END{print NR}'

O Ruby recebe esse recurso por meio do Perl, que utilizou o AWK como uma maneira de integrar os administradores de sistemas com o Perl sem precisar alterar a maneira como eles fazem as coisas.

Pinochle
fonte
1
Gostaria de acrescentar que o suporte à linha de comando do Python é bastante fraco. Além do loop automático ausente, você não pode colocar algumas instruções em uma única linha e passá-lo como um argumento de linha de comando de cadeia única para o intérprete. Pelo menos eu não fiz isso.
ThomasH
Claro que você pode. Mas você (como em qualquer outro idioma) precisará incluir entre aspas.
Lennart Regebro 15/10/09
Python não é feito para ser usado na linha de comando, uma vez que você tem que ser explícito sobre algumas coisas (como sys.stdin) se você quiser usá-lo dessa formapython -c "import sys; print len(list(sys.stdin))"
u0b34a0f6ae
5

Ruby tem sigilos e galhos, Python não.

Edit : E uma coisa muito importante que eu esqueci (afinal, o anterior foi apenas para queimar um pouco :-p):

O Python possui um compilador JIT ( Psyco ), uma linguagem de nível mais baixo para escrever código mais rápido ( Pyrex ) e a capacidade de adicionar código C ++ embutido ( Weave ).

fortran
fonte
É verdade, mas isso é apenas sintaxe.
Lennart Regebro 11/07/2009
6
Bem, se você quiser seguir esse caminho: ambos são completos de Turing. Tudo o resto é apenas sintaxe.
Jörg W Mittag
Sim e uma diferença de sintaxe importax ;-)
fortran
1
Qual a importância de escrever @foo ou self.foo?
Lennart Regebro 11/07/2009
1
@ Jörg: OK, chame de algo mais que "sintaxe" então. O ponto é que @foo e self.foo fazem a mesma coisa, na verdade não é uma funcionalidade que Ruby tenha e Python não.
Lennart Regebro 11/07/2009
5

Meu python está enferrujado, então alguns deles podem estar em python e eu simplesmente não me lembro / nunca aprendi, mas aqui estão os primeiros que eu pensei:

Espaço em branco

Ruby lida com espaço em branco completamente diferente. Para iniciantes, você não precisa recuar nada (o que significa que não importa se você usa 4 espaços ou 1 guia). Ele também faz a continuação da linha inteligente; portanto, o seguinte é válido:

def foo(bar,
        cow)

Basicamente, se você terminar com um operador, ele descobrirá o que está acontecendo.

Mixins

O Ruby possui mixins que podem estender instâncias em vez de classes completas:

module Humor
  def tickle
    "hee, hee!"
  end
end
a = "Grouchy"
a.extend Humor
a.tickle    »   "hee, hee!"

Enums

Não tenho certeza se isso é o mesmo que geradores, mas no Ruby 1.9 ruby ​​como enums, então

>> enum = (1..4).to_enum
=> #<Enumerator:0x1344a8>

Referência: http://blog.nuclearsquid.com/writings/ruby-1-9-what-s-new-what-s-changed

"Argumentos de palavras-chave"

Ambos os itens listados são suportados no Ruby, embora você não possa pular valores padrão como esse. Você pode ir em ordem

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

Observe que c = 5 realmente atribui a variável c no escopo da chamada ao valor 5 e define o parâmetro b ao valor 5.

ou você pode fazer isso com hashes, que abordam o 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

Referência: Guia Pragmático do Programador para Ruby

Scott Dugas
fonte
Seu segundo exemplo foo (1, c = 5) não faz o que você pensa que faz. Ruby não possui parâmetros nomeados.
Horseyguy 03/08/09
5
Python tem linha implícita continuação dentro de colchetes (, [ou{
u0b34a0f6ae
5

Você pode ter código na definição de classe em Ruby e Python. No entanto, no Ruby você tem uma referência à classe (self). No Python, você não tem uma referência à classe, pois a classe ainda não está definida.

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.

Lennart Regebro
fonte
Você pode fornecer mais detalhes (como código) para o seu primeiro ponto?
11389 Loïc Wolff
Exemplo de código é uma boa ideia, acrescentei que, embora este caso seja trivial.
Lennart Regebro 11/07/2009
@ SilentGhost: Não consigo pensar em um que não seja realmente obscuro no momento. :)
Lennart Regebro 11/07/2009
você pode acessar o nome da classe dentro da classe em python: foo classe (): def o init __ (self): print self .__ classe .__ name__
txwikinger
1
@ txwikinger: sim, mas não dentro do corpo da classe, que é executado ao mesmo tempo que a classinstrução.
Bastien Léonard
4

A sintaxe não é uma coisa pequena, tem um impacto direto em como pensamos. Também afeta diretamente as regras que criamos para os sistemas que usamos. Como exemplo, temos a ordem das operações devido à maneira como escrevemos equações ou sentenças matemáticas. A notação padrão para matemática permite que as pessoas leiam mais de uma maneira e cheguem a respostas diferentes, dada a mesma equação. Se tivéssemos usado notação de prefixo ou postfix, teríamos criado regras para distinguir quais eram os números a serem manipulados, em vez de apenas ter regras para a ordem na qual calcular valores.

A notação padrão deixa claro de quais números estamos falando e, ao mesmo tempo, torna a ordem na qual eles são ambíguos. A notação de prefixo e postfix faz a ordem na qual calcular com simplicidade, tornando os números ambíguos. O Python já teria lambdas multilinhas se não fosse pelas dificuldades causadas pelo espaço em branco sintático. (Existem propostas para realizar esse tipo de coisa sem necessariamente adicionar delimitadores de bloco explícitos.)

Acho mais fácil escrever condições em que desejo que algo ocorra, se uma condição for falsa, muito mais fácil escrever com a instrução a menos em Ruby do que a construção "se-não" semanticamente equivalente em Ruby ou em outros idiomas, por exemplo. Se a maioria dos idiomas que as pessoas estão usando hoje tem o mesmo poder, como a sintaxe de cada idioma pode ser considerada trivial? Após recursos específicos, como blocos e mecanismos de herança, etc. a sintaxe é a parte mais importante de uma linguagem, dificilmente uma coisa superficial.

O que é superficial são as qualidades estéticas da beleza que atribuímos à sintaxe. A estética não tem nada a ver com o funcionamento da nossa cognição, a sintaxe.

habilidade de sombra
fonte
Esse "comentário" é três vezes maior do que o permitido em um comentário, independentemente do representante.
Andrew Grimm
Isso realmente parece bom como uma resposta para mim. Editado o bit "isto é um comentário".
Bill the Lizard
3

Surpreso ao ver nada mencionado sobre o mecanismo "falta de método" de ruby. Eu daria exemplos dos métodos find_by _... no Rails, como um exemplo do poder desse recurso de linguagem. Meu palpite é que algo semelhante poderia ser implementado em Python, mas, pelo que sei, não existe de forma nativa.

MikeIsGo
fonte
O Python possui get_attribute , que realiza basicamente o mesmo que o método de Ruby.
Mipadi
3
Por que os desenvolvedores de python sempre se machucam quando o ruby ​​é mencionado em QUALQUER LUGAR? Você não pode negar que isso não é verdade.
AaronA
method_missingpode ser emulada em Python em alguns casos: class M(): def __getattr__(self, n): return lambda: "Missing! " + n; M().hi(). No entanto, existem pequenas diferenças e eu duvido que seja idiomática em Python :-)
1
@DJTripleThreat: Eu nego que seja verdade.
Lennart Regebro
3

Outra diferença nas lambdas entre Python e Ruby é demonstrada pelo problema do gerador de acumulador de Paul Graham . Reproduzido aqui:

Escreva uma função foo que pega um número n e retorna uma função que pega um número ie retorna n incrementado por i. Nota: (a) esse é o número, não inteiro, (b) é incrementado por, não mais.

No Ruby, você pode fazer isso:

def foo(n)
  lambda {|i| n += i }
end

No Python, você criaria um objeto para armazenar o estado de n:

class foo(object):
    def __init__(self, n):
        self.n = n
    def __call__(self, i):
        self.n += i
        return self.n

Algumas pessoas podem preferir a abordagem explícita do Python como sendo mais clara conceitualmente, mesmo que seja um pouco mais detalhada. Você armazena o estado como faz para qualquer outra coisa. Você só precisa entender a idéia de objetos que podem ser chamados. Mas, independentemente de qual abordagem se preferir esteticamente, mostra um respeito pelo qual as lambdas do Ruby são construções mais poderosas do que as do Python.

dormsbee
fonte
3
Você não pode incrementar números no Python, de modo que a restrição não faz sentido. No Python, os números são imutáveis. Se mudarmos para "mais", a classe será desnecessária. Portanto, isso não demonstra nada sobre a diferença lambda, mas a diferença em como os números funcionam. A menos que você crie uma classe de número mutável. :)
Lennart Regebro
2
A restrição existe para esclarecer o comportamento desejado. O que o problema está pedindo é: f = foo (10) f (2) >> 12 f (3) >> 15 ... lambda {| i | n + i} dá: f = foo (10) f (2) >> 12 f (3) >> 13 ... Os números também são imutáveis ​​no Ruby - você não pode dizer 2 + = 1, por exemplo. E n + = 1 é bom em uma função Python regular, mas não em uma lambda. Portanto, é uma questão do que "n" é, o fato de ser criado quando a função é chamada e a lambda formada, que você pode fazer a atribuição em uma lambda (em vez de apenas expressões) e que pode conter o valor de n através de várias chamadas.
dormsbee
Eu não acho que você precise se esforçar tanto em Python. As funções podem ser definidas dentro de outras funções. def foo(n): def f(i): return n + i return f.
FMc
2
Ainda não é o mesmo, e seu exemplo é equivalente ao lambda Python no comentário acima. A versão Ruby cria um lambda que mantém o estado entre as chamadas. O exemplo que você postou permite configurar um valor inicial para n, mas a função que foo retorna sempre terá esse valor inicial. A versão do Ruby é incrementada. Então, digamos f = foo (10). A versão do Python: f (1) => 11, f (1) => 11. A versão do Ruby f.call (1) => 11, f.call (1) => 12.
dormsbee
def foo(n): L=[n] def f(i): L[0] += i return L[0] return f. No Python3, você pode usar a nonlocalpalavra-chave
perfil completo de jfs
3

python nomeou argumentos opcionais

def func(a, b=2, c=3):
    print a, b, c

>>> func(1)
1 2 3
>>> func(1, c=4)
1 2 4

O AFAIK Ruby apenas posicionou argumentos porque b = 2 na declaração da função é uma afetação que sempre é anexada.

Batiste Bieler
fonte
3
o que "Ruby apenas posicionou argumentos porque b = 2 na declaração de função é uma afetação que sempre acrescenta" significa?
Horseyguy 29/07/09
3
Não sei em que planeta você vive, mas def my_method(param1, optional = false)funciona no Ruby 1.8.6, 1.8.7 e, presumivelmente, 1.9!
Robert K
5
The Wicked Flea, e as pessoas que votaram positivamente no seu comentário, você não olhou o exemplo de perto. Ele é capaz de pular o bparâmetro na funcchamada e ainda mantém seu padrão. Ou seja, bé o segundo argumento da assinatura, mas ele pode ignorá-lo prefixando o segundo parâmetro com c=. Ruby usa hashes para simular isso, mas não é exatamente o mesmo.
Maček
2

Ruby incorporou documentação:

 =begin

 You could use rdoc to generate man pages from this documentation

 =end
ko-dos
fonte
5
Os documentos acabam como parte dos métodos / classes em que você os define. Assim você pode fazer ajuda (classe) e vai mostrar-lhe as docstrings, etc.
Lennart Regebro
2

No Ruby, quando você importa um arquivo com require, todas as coisas definidas nesse arquivo acabam no seu namespace global.

Com o Cargo, você pode " exigir bibliotecas sem sobrecarregar seu espaço para nome ".

# 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 = importação ("foo-1.0.0")
>> Foo2 = importação ("foo-2.0.0")
>> Foo1 :: VERSÃO
=> "1.0.0"
>> Foo2 :: VERSÃO
=> "2.0.0"
Jonas Elfström
fonte
Isso deveria ter sido um comentário, não uma nova resposta.
Lennart Regebro