Estou tentando entender, o que é um patch de macaco ou um patch de macaco?
Isso é algo como métodos / operadores sobrecarregando ou delegando?
Tem algo em comum com essas coisas?
Estou tentando entender, o que é um patch de macaco ou um patch de macaco?
Isso é algo como métodos / operadores sobrecarregando ou delegando?
Tem algo em comum com essas coisas?
Respostas:
Não, não é como nenhuma dessas coisas. É simplesmente a substituição dinâmica de atributos em tempo de execução.
Por exemplo, considere uma classe que possui um método get_data
. Esse método faz uma pesquisa externa (em um banco de dados ou API da web, por exemplo) e vários outros métodos da classe o chamam. No entanto, em um teste de unidade, você não deseja depender da fonte de dados externa - portanto, substitui dinamicamente o get_data
método por um stub que retorna alguns dados fixos.
Como as classes Python são mutáveis e os métodos são apenas atributos da classe, você pode fazer isso o quanto quiser - e, de fato, pode até substituir classes e funções em um módulo exatamente da mesma maneira.
Mas, como comentou um comentarista , tenha cuidado ao monkeypatching:
Se algo além de sua lógica de teste exigir get_data
, também chamará sua substituição corrigida pelo macaco em vez da original - o que pode ser bom ou ruim. Apenas tenha cuidado.
Se existir alguma variável ou atributo que também aponte para a get_data
função no momento da substituição, esse alias não alterará seu significado e continuará apontando para o original get_data
. (Por quê? O Python apenas religa o nome get_data
da sua classe a algum outro objeto de função; outras associações de nome não são afetadas.)
pointing to the original get_data function
? Você quer dizer quando armazena uma função dentro de uma variável se alguém alterar essa função, a variável continuará apontando para a antiga?
get_data
, você renova o nome get_data
para uma função simulada. Se algum outro nome em algum outro lugar do programa estiver vinculado à função anteriormente conhecida como- get_data
, nada será alterado para esse outro nome.
Um MonkeyPatch é um pedaço de código Python que estende ou modifica outro código em tempo de execução (normalmente na inicialização).
Um exemplo simples é assim:
from SomeOtherProduct.SomeModule import SomeClass
def speak(self):
return "ook ook eee eee eee!"
SomeClass.speak = speak
Fonte: Página MonkeyPatch no wiki do Zope.
O que é um patch de macaco?
Simplificando, o patch do macaco está fazendo alterações em um módulo ou classe enquanto o programa está sendo executado.
Há um exemplo de patch de macaco na documentação do Pandas:
import pandas as pd
def just_foo_cols(self):
"""Get a list of column names containing the string 'foo'
"""
return [x for x in self.columns if 'foo' in x]
pd.DataFrame.just_foo_cols = just_foo_cols # monkey-patch the DataFrame class
df = pd.DataFrame([list(range(4))], columns=["A","foo","foozball","bar"])
df.just_foo_cols()
del pd.DataFrame.just_foo_cols # you can also remove the new method
Para dividir isso, primeiro importamos nosso módulo:
import pandas as pd
Em seguida, criamos uma definição de método, que existe ilimitada e livre fora do escopo de qualquer definição de classe (uma vez que a distinção é bastante sem sentido entre uma função e um método não vinculado, o Python 3 elimina o método não vinculado):
def just_foo_cols(self):
"""Get a list of column names containing the string 'foo'
"""
return [x for x in self.columns if 'foo' in x]
Em seguida, simplesmente anexamos esse método à classe em que queremos usá-lo:
pd.DataFrame.just_foo_cols = just_foo_cols # monkey-patch the DataFrame class
E então podemos usar o método em uma instância da classe e excluir o método quando terminarmos:
df = pd.DataFrame([list(range(4))], columns=["A","foo","foozball","bar"])
df.just_foo_cols()
del pd.DataFrame.just_foo_cols # you can also remove the new method
Se você estiver usando nomes diferentes (prefixar atributos com um sublinhado duplo, que altera o nome e que eu não recomendo), será necessário alterar o nome manualmente, se você fizer isso. Como eu não recomendo o nome errado, não o demonstrarei aqui.
Como podemos usar esse conhecimento, por exemplo, em testes?
Digamos que precisamos simular uma chamada de recuperação de dados para uma fonte de dados externa que resulte em um erro, porque queremos garantir o comportamento correto nesse caso. Podemos aplicar um patch na estrutura de dados para garantir esse comportamento. (Então, usando um nome de método semelhante ao sugerido por Daniel Roseman :)
import datasource
def get_data(self):
'''monkey patch datasource.Structure with this to simulate error'''
raise datasource.DataRetrievalError
datasource.Structure.get_data = get_data
E quando testamos o comportamento que depende desse método que gera um erro, se implementado corretamente, obteremos esse comportamento nos resultados do teste.
Ao fazer o procedimento acima, o Structure
objeto será alterado durante toda a vida útil do processo, portanto, convém usar configurações e desmontagens em seus unittests para evitar isso, por exemplo:
def setUp(self):
# retain a pointer to the actual real method:
self.real_get_data = datasource.Structure.get_data
# monkey patch it:
datasource.Structure.get_data = get_data
def tearDown(self):
# give the real method back to the Structure object:
datasource.Structure.get_data = self.real_get_data
(Embora o que foi dito acima seja bom, provavelmente seria uma idéia melhor usar a mock
biblioteca para corrigir o código. mock
O patch
decorador do código seria menos propenso a erros do que o descrito acima, o que exigiria mais linhas de código e, portanto, mais oportunidades para introduzir erros. Ainda tenho que revisar o código, mock
mas imagino que ele use o patch para macacos de maneira semelhante.)
De acordo com a Wikipedia :
No Python, o termo patch de macaco refere-se apenas a modificações dinâmicas de uma classe ou módulo em tempo de execução, motivadas pela intenção de corrigir o código de terceiros existente como uma solução alternativa para um bug ou recurso que não age como você deseja.
Primeiro: patch de macacos é um truque do mal (na minha opinião).
É frequentemente usado para substituir um método no nível do módulo ou da classe por uma implementação personalizada.
O caso de usuário mais comum é adicionar uma solução alternativa para um bug em um módulo ou classe quando você não pode substituir o código original. Nesse caso, você substitui o código "errado" através do patch do macaco por uma implementação dentro do seu próprio módulo / pacote.
O patch para macacos só pode ser feito em linguagens dinâmicas, das quais python é um bom exemplo. Alterar um método no tempo de execução, em vez de atualizar a definição do objeto, é um exemplo; da mesma forma, adicionar atributos (métodos ou variáveis) ao tempo de execução é considerado uma correção de macaco. Isso geralmente é feito ao trabalhar com módulos para os quais você não possui a fonte, de modo que as definições de objetos não possam ser facilmente alteradas.
Isso é considerado ruim porque significa que a definição de um objeto não descreve completamente ou com precisão como ele realmente se comporta.
O patch para macacos está reabrindo as classes ou métodos existentes na classe em tempo de execução e alterando o comportamento, que deve ser usado com cautela, ou você deve usá-lo somente quando realmente precisar.
Como o Python é uma linguagem de programação dinâmica, as Classes são mutáveis para que você possa reabri-las e modificá-las ou até substituí-las.
O que é o patch de macacos? O patch para macacos é uma técnica usada para atualizar dinamicamente o comportamento de um pedaço de código em tempo de execução.
Por que usar patch de macaco? Ele nos permite modificar ou estender o comportamento de bibliotecas, módulos, classes ou métodos em tempo de execução sem modificar o código-fonte
Conclusão O patch do macaco é uma técnica interessante e agora aprendemos como fazer isso no Python. No entanto, como discutimos, ele tem suas próprias desvantagens e deve ser usado com cuidado.
Para obter mais informações, consulte [1]: https://medium.com/@nagillavenkatesh1234/monkey-patching-in-python-explained-with-examples-25eed0aea505
Monkey patching is a technique to add, modify, or suppress the default behavior of a piece of code at runtime without changing its original source code.