Pergunta

Em muitas discussões tenho ouvido sobre Ruby em que as pessoas têm manifestado as suas reservas sobre a língua, a questão da aplicação de patches macaco surge como uma das suas principais preocupações.

No entanto, eu raramente ouvir os mesmos argumentos apresentados no contexto do Python embora também seja permitida na linguagem Python.

Por que essa distinção?

O Python incluem diferentes tipos de salvaguardas para minimizar os riscos de esse recurso?

Foi útil?

Solução

Como um programador Python que teve um gosto de Ruby (e gosta), eu acho que há um pouco de um paralelo irônico quando Python estava começando a se tornar popular.

programadores C e Java iria ‘bash’ Python, afirmando que não era uma língua real, e que a natureza dinâmica de seus tipos seria perigoso, e permitir que as pessoas a criar código ‘mau’. Como Python tornou-se mais popular, e as vantagens de seu tempo rápido desenvolvimento tornou-se evidente, para não mencionar a menos detalhada sintaxe:

// Java
Person p = new Person();
# Python
p = Person()

começamos a ver algumas características mais dinâmicas aparecem em versões posteriores do Java. Autoboxing e -unboxing torná-lo menos problemático para lidar com primitivas, e Genéricos nos permitem código uma vez e aplicá-lo a muitos tipos.

Foi com algum divertimento que eu vi uma das características flexíveis principais do Ruby - Monkey Patching, sendo apontado como perigoso pela multidão Python. Tendo começado a ensinar Ruby para os alunos este ano, acho que ser capaz de ‘consertar’ a implementação de uma classe existente, mesmo um que é parte do sistema, é muito poderoso.

Claro, você pode estragar mal e seu programa pode falhar. Posso segfault em C muito facilmente também. E os aplicativos Java podem morrer em chamas morte.

A verdade é que eu vejo Macaco Patching como o próximo passo na dinâmica e meta-programação. Engraçado, uma vez que tem sido em torno desde Smalltalk.

Outras dicas

É uma técnica menos praticada em Python, em parte porque as classes "core" em Python (aqueles implementados em C) não são realmente modificável. Em Ruby, por outro lado, devido à maneira como ele é implementado internamente (não melhor, apenas diferente) apenas sobre qualquer coisa pode ser modificado de forma dinâmica.

Filosoficamente, é algo que tende a ser visto com bons olhos dentro da comunidade Python, claramente menos assim no mundo Ruby. Eu não sei por que você afirma que é mais controversa (você pode conectar-se a uma referência de autoridade?) -. Minha experiência tem sido esse macaco-patching é uma técnica aceita se aquele em que o usuário deve estar ciente das possíveis consequências

As línguas pode permitir isso, mas nem comunidade tolera a prática. Monkeypatching não é tolerado em qualquer idioma, mas você ouvir sobre isso com mais frequência em Ruby porque a forma de classe aberta que utiliza torna muito, muito fácil de monkeypatch uma classe e, por isso, é mais aceitável na comunidade ruby, mas ainda desaprovada . Monkeypatching simplesmente não é tão prevalente ou tão fácil em Python, que é por isso que você não vai ouvir os mesmos argumentos contra ela naquela comunidade. Python não faz nada que Ruby não fazer para evitar a prática.

A razão que você ouvir / ler sobre isso com mais frequência em Ruby é que isso em Ruby:

class MyClass
  def foo
    puts "foo"
  end
end
class MyClass
  def bar
    puts "bar"
  end
end

lhe dará uma classe que contém dois métodos, foo e bar, enquanto isso em Python:

class MyClass:
    def foo(self):
        print "foo"
class MyClass:
    def bar(self):
        print "bar"

vai deixar você com uma classe que contém apenas o bar método, como redefinição de uma classe clobbers a definição anterior completamente. Para monkeypatch em Python, você realmente tem que escrever o seguinte:

class MyClass:
    def foo(self):
        print "foo"
def bar(self):
    print "bar"
MyClass.bar = bar

que é mais difícil do que a versão Ruby. Isso por si só marcas código Ruby muito mais fácil monkeypatch do que o código Python.

"Does Python incluem diferentes tipos de salvaguardas para minimizar os riscos de esse recurso?"

Sim. A comunidade se recusa a fazê-lo. A salvaguarda é inteiramente social.

Na verdade em Python é um pouco mais difícil de modificar tipos básicos.

Por exemplo, imagine que você redefinir inteiro.

Ruby:

class Fixnum 
   def *(n)
      5 
   end 
end

Agora 2 * 2 rendimentos 5.

Python:

>>> class int(int):
    def __mul__(self, x):
        return 5


>>> 2*2
4
>>> int(2)*int(2)
5

Em Python, qualquer literal ("", {}, 1.0, etc) cria uma instância da classe standard, mesmo se você tentou monkeypatch-lo e redefiniu a classe correspondente no espaço de nomes.

Ele só não vai funcionar como pretendido:

class str():
    # define your custom string type
    ...

a = "foo"      # still a real Python string
a = str("foo") # only this uses your custom class

Eu acho que patching macaco só deve ser usado como a última solução.

programadores Normalmente Python saber como uma classe ou uma comportam método. Eles sabem que xxx classe está fazendo as coisas de uma certa maneira.

Quando você macaco corrigir uma classe ou um método, você está mudando seu comportamento. Outros programadores Python usando esta classe pode ser muito surpreso se essa classe está se comportando de forma diferente.

A maneira normal de fazer as coisas é subclasse. Dessa forma, outros programadores sabem que eles estão usando um objeto diferente. Eles podem usar a classe original ou a subclasse, se optar por.

Se você quiser fazer alguma patching macaco em Python, é relativamente fácil, desde que você não está modificando um built-in tipo (int, float, str).

class SomeClass:
    def foo(self):
        print "foo"

def tempfunc(self):
    print "bar"
SomeClass.bar = tempfunc
del tempfunc

Isto irá adicionar o método bar para SomeClass e casos ainda existentes de que a classe pode usar esse método injetado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top