Sto cercando di capire, cos'è il patch di scimmia o un patch di scimmia?
È qualcosa come metodi / operatori che sovraccaricano o delegano?
Ha qualcosa in comune con queste cose?
Sto cercando di capire, cos'è il patch di scimmia o un patch di scimmia?
È qualcosa come metodi / operatori che sovraccaricano o delegano?
Ha qualcosa in comune con queste cose?
Risposte:
No, non è come nessuna di quelle cose. È semplicemente la sostituzione dinamica degli attributi in fase di esecuzione.
Ad esempio, considera una classe che ha un metodo get_data
. Questo metodo esegue una ricerca esterna (su un database o un'API Web, ad esempio), e vari altri metodi nella classe lo chiamano. Tuttavia, in un unit test, non si desidera dipendere dall'origine dati esterna, quindi sostituire in modo dinamico il get_data
metodo con uno stub che restituisce alcuni dati fissi.
Poiché le classi Python sono mutabili e i metodi sono solo attributi della classe, puoi farlo come preferisci e, in effetti, puoi persino sostituire classi e funzioni in un modulo esattamente nello stesso modo.
Ma, come ha sottolineato un commentatore , fai attenzione quando monkeypatching:
Se qualcos'altro oltre alla tua logica di test chiama get_data
anche, chiamerà anche la tua sostituzione con patch scimmia piuttosto che l'originale - che può essere buona o cattiva. Attenzione.
Se esiste qualche variabile o attributo che punta anche alla get_data
funzione al momento della sostituzione, questo alias non cambierà il suo significato e continuerà a puntare all'originale get_data
. (Perché? Python abbina semplicemente il nome get_data
nella tua classe a qualche altro oggetto funzione; gli altri collegamenti ai nomi non hanno alcun impatto.)
pointing to the original get_data function
? Intendi quando memorizzi una funzione all'interno di una variabile se qualcuno cambia quella funzione continuerà a puntare a quella vecchia?
get_data
, si associa il nome get_data
a una funzione simulata. Se un altro nome da qualche altra parte nel programma è associato alla funzione precedentemente nota come as get_data
, nulla cambierà per quell'altro nome.
Un MonkeyPatch è un pezzo di codice Python che estende o modifica altro codice in fase di esecuzione (in genere all'avvio).
Un semplice esempio è simile al seguente:
from SomeOtherProduct.SomeModule import SomeClass
def speak(self):
return "ook ook eee eee eee!"
SomeClass.speak = speak
Fonte: pagina MonkeyPatch sul wiki di Zope.
Cos'è una patch scimmia?
In poche parole, il patching delle scimmie sta apportando modifiche a un modulo o a una classe mentre il programma è in esecuzione.
C'è un esempio di patching delle scimmie nella documentazione di 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
Per scomporlo, prima di tutto importiamo il nostro modulo:
import pandas as pd
Quindi creiamo una definizione di metodo, che esiste senza restrizioni e libera al di fuori dell'ambito di qualsiasi definizione di classe (poiché la distinzione è abbastanza insignificante tra una funzione e un metodo non associato, Python 3 elimina il metodo non associato):
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]
Quindi colleghiamo semplicemente quel metodo alla classe su cui vogliamo usarlo:
pd.DataFrame.just_foo_cols = just_foo_cols # monkey-patch the DataFrame class
Quindi possiamo usare il metodo su un'istanza della classe ed eliminare il metodo quando abbiamo finito:
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 stai usando il name-mangling (prefisso gli attributi con un doppio trattino basso, che altera il nome e che non ti consiglio) dovrai farlo manualmente. Dal momento che non raccomando di cambiare nome, non lo dimostrerò qui.
Come possiamo usare questa conoscenza, ad esempio, nei test?
Supponiamo di dover simulare una chiamata di recupero dati a un'origine dati esterna che si traduca in un errore, perché in tal caso vogliamo garantire un comportamento corretto. Siamo in grado di applicare una patch alla struttura dei dati per garantire questo comportamento. (Quindi usando un nome di metodo simile a quello suggerito da 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 lo testiamo per un comportamento che si basa su questo metodo generando un errore, se implementato correttamente, otterremo quel comportamento nei risultati del test.
Basta fare quanto sopra per modificare l' Structure
oggetto per la durata del processo, quindi ti consigliamo di utilizzare impostazioni e smontaggi nei tuoi unittest per evitare di farlo, ad esempio:
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
(Mentre quanto sopra va bene, probabilmente sarebbe una migliore idea usare la mock
libreria per patchare il codice. mock
Il patch
decoratore sarebbe meno soggetto ad errori rispetto a quanto sopra, il che richiederebbe più righe di codice e quindi maggiori opportunità di introdurre errori Devo ancora rivedere il codice mock
ma immagino che usi il patching delle scimmie in un modo simile.)
Secondo Wikipedia :
In Python, il termine scimmia patch si riferisce solo a modifiche dinamiche di una classe o di un modulo in fase di runtime, motivati dall'intento di correggere codice di terze parti esistente come soluzione alternativa a un bug o a una funzionalità che non agisce come desiderato.
Primo: il patching delle scimmie è un trucco malvagio (secondo me).
Viene spesso utilizzato per sostituire un metodo a livello di modulo o di classe con un'implementazione personalizzata.
L'usecase più comune è l'aggiunta di una soluzione alternativa per un bug in un modulo o in una classe quando non è possibile sostituire il codice originale. In questo caso si sostituisce il codice "errato" tramite patch scimmia con un'implementazione all'interno del proprio modulo / pacchetto.
Il patching delle scimmie può essere eseguito solo in linguaggi dinamici, di cui python è un buon esempio. La modifica di un metodo in fase di esecuzione anziché l'aggiornamento della definizione dell'oggetto è un esempio; allo stesso modo, l'aggiunta di attributi (sia metodi che variabili) in fase di esecuzione è considerata patch scimmia. Ciò avviene spesso quando si lavora con moduli per i quali non si ha l'origine, in modo tale che le definizioni degli oggetti non possano essere facilmente modificate.
Ciò è considerato negativo perché significa che la definizione di un oggetto non descrive in modo completo o accurato come si comporta effettivamente.
Il patching delle scimmie sta riaprendo le classi o i metodi esistenti in classe in fase di runtime e sta cambiando il comportamento, che dovrebbe essere usato con cautela, oppure dovresti usarlo solo quando è realmente necessario.
Poiché Python è un linguaggio di programmazione dinamico, le Classi sono mutabili in modo da poterle riaprire e modificare o persino sostituirle.
Cos'è il patching delle scimmie? Il patching delle scimmie è una tecnica utilizzata per aggiornare dinamicamente il comportamento di un pezzo di codice in fase di esecuzione.
Perché usare il patching delle scimmie? Ci consente di modificare o estendere il comportamento di librerie, moduli, classi o metodi in fase di runtime senza modificare effettivamente il codice sorgente
Conclusioni Il patching delle scimmie è una tecnica interessante e ora abbiamo imparato a farlo in Python. Tuttavia, come abbiamo discusso, ha i suoi svantaggi e dovrebbe essere usato con attenzione.
Per maggiori informazioni, fare riferimento a [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.