Monkey Patch
Motivado pelos posts sobre paradigmas de programação escritos pelo Ronaldo Ferraz e a uma discussão sobre como alterar uma classe em tempo de execução no Python, resolvi escrever sobre esse assunto aqui no blog.
Moneky Patch é como é chamada a possibilidade de poder alterar uma classe em tempo de execução. Existem linguagens em que o Monkey Patch é muito utilizado, como o Ruby, mas é possível utilizar essa técnica em Python também.
Em Ruby para alterar uma classe basta apenas chamar a classe novamente e assim extendê-la:
Vamos criar uma classe chamada Teste:
class Teste
def oi
puts 'oi'
end
end
Vamos alterar ela. Como citei acima basta apenas recriar ela com o novo método:
class Teste
def ola
puts 'ola'
end
end
Em Ruby é permitido alterar classes nativas e métodos já existentes. Dessa forma se eu quiser adicionar um método a classe String eu posso.
class String
def conta
return self.size()
end
end
Em Python as coisas funcionam um pouco diferente. Vamos criar uma classe sem métodos chamada Teste:
>>>class Teste: pass
>>> dir(Teste)
['__doc__', '__module__']
Vamos criar uma função para adicionar futuramente como método a classe Teste
>>> def oi(self): print 'oi'
Para adicionar essa função como método da classe basta criar um atributo na classe e atribuir a função a esse atributo da seguinte maneira:
>>> Teste.oi = oi
E para confirmar que está tudo funcionando como esperado, vamos criar uma instância para a classe Teste e executar o método oi:
>>> teste = Teste()
>>> teste.oi()
oi
Outra forma de adicionarmos um método a uma classe é usando o método setattr:
>>>setattr(Teste, oi.__name__, oi)
Agora com esse conhecimento é possível, automatizar isso criando decorators ou metaclasses como num exemplo dado pelo Guido van Rossum.
Só uma observação. Diferente de Ruby, no Python não é possivel fazer monkey patch em classes built-in como str, int, list.
Vamos a um exemplo:
>>> def conta(self): print len(self)
>>> setattr(str, conta.__name__, conta)
Traceback (most recent call last):
File "", line 1, in
TypeError: can't set attributes of built-in/extension type 'str'
Para finalizar, ter o recurso do monkey patch numa linguagem é algo muito poderoso, e alguém já disse que 'com grandes poderes, vem grandes responsabilidades'. Se você alterar uma classe usando o monkey patch com um método que já existe nessa classe, isso pode ser algo bem traiçoeiro.
Ótimo post. Acho que o caminho das letras está sendo novamente encontrado. Boa sorte ;)
Março 21, 2008 as 8:58 p.m.Esse problema de modificar métodos existentes fica mais interessante quando a classe é compartilhada com outros módulos aos quais o programador não tem acesso.
- "Você precisa do documento XYZ".
- "Mas lá em MNO me deram o documento ABC".
- "Problema seu, só aceitamos XYZ"...
PS: Van Russel ou Van Rossum? =)
Março 22, 2008 as 2:30 a.m.Van Russel? Vin Diesel? :)
Aliás, o link sobre monkeypatch que você compartilhou no google reader é muito interessante. Abraço!
Março 22, 2008 as 4:16 p.m.Da onde eu tirei esse Russel? :-)
Março 23, 2008 as 11:20 p.m.