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?
python
terminology
monkeypatching
Sergei Basharov
fonte
fonte
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.
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 oget_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 originalget_data
. (Por quê? O Python apenas religa o nomeget_data
da sua classe a algum outro objeto de função; outras associações de nome não são afetadas.)fonte
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 nomeget_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 exemplo simples é assim:
Fonte: Página MonkeyPatch no wiki do Zope.
fonte
Simplificando, o patch do macaco está fazendo alterações em um módulo ou classe enquanto o programa está sendo executado.
Exemplo em uso
Há um exemplo de patch de macaco na documentação do Pandas:
Para dividir isso, primeiro importamos nosso módulo:
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):
Em seguida, simplesmente anexamos esse método à classe em que queremos usá-lo:
E então podemos usar o método em uma instância da classe e excluir o método quando terminarmos:
Advertência para desconfiar de nomes
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.
Exemplo de teste
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 :)
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:(Embora o que foi dito acima seja bom, provavelmente seria uma idéia melhor usar a
mock
biblioteca para corrigir o código.mock
Opatch
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.)fonte
De acordo com a Wikipedia :
fonte
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.
fonte
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.
fonte
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.
fonte
Para obter mais informações, consulte [1]: https://medium.com/@nagillavenkatesh1234/monkey-patching-in-python-explained-with-examples-25eed0aea505
fonte