826 Stimmen

Was ist Affe Parcheando?

Ich versuche zu verstehen, was ein Affe Parcheando oder ein Affenpflaster ist?

Ist das so etwas wie Methoden/Operatoren überladen oder delegieren?

Hat es etwas mit diesen Dingen gemeinsam?

744voto

Daniel Roseman Punkte 565786

Nein, es ist nichts von alledem. Es handelt sich lediglich um die dynamische Ersetzung von Attributen zur Laufzeit.

Nehmen wir zum Beispiel eine Klasse, die eine Methode hat get_data . Diese Methode führt eine externe Suche durch (z. B. in einer Datenbank oder einer Web-API), und verschiedene andere Methoden in der Klasse rufen sie auf. In einem Einheitstest möchten Sie jedoch nicht von der externen Datenquelle abhängig sein - daher ersetzen Sie dynamisch die get_data Methode mit einem Stub, der einige feste Daten zurückgibt.

Da Python-Klassen veränderbar sind und Methoden nur Attribute der Klasse sind, können Sie dies so oft tun, wie Sie wollen - und tatsächlich können Sie sogar Klassen und Funktionen in einem Modul auf genau dieselbe Weise ersetzen.

Aber, als Kommentator darauf hingewiesen, dass beim Monkeypatching Vorsicht geboten ist:

  1. Wenn irgendetwas anderes als Ihre Testlogik die get_data wird auch Ihr von einem Affen gepatchter Ersatz aufgerufen und nicht das Original - was gut oder schlecht sein kann. Seien Sie einfach vorsichtig.

  2. Wenn es eine Variable oder ein Attribut gibt, das ebenfalls auf den get_data Funktion zu ersetzen, ändert dieser Alias seine Bedeutung nicht und verweist weiterhin auf die ursprüngliche get_data . (Warum? Python bindet den Namen einfach neu ein. get_data in Ihrer Klasse auf ein anderes Funktionsobjekt; andere Namensbindungen sind davon überhaupt nicht betroffen).

453voto

Paolo Punkte 18132

Ein MonkeyPatch ist ein Teil des Python-Codes, der eine Erweiterung oder Änderung der anderen Code zur Laufzeit erweitert oder verändert (typischerweise beim Starten).

Ein einfaches Beispiel sieht wie folgt aus:

from SomeOtherProduct.SomeModule import SomeClass

def speak(self):
    return "ook ook eee eee eee!"

SomeClass.speak = speak

Quelle: MonkeyPatch Seite im Zope-Wiki.

168voto

Was ist ein Affenpflaster?

Einfach ausgedrückt, macht monkey Parcheando Änderungen an einem Modul oder einer Klasse, während das Programm läuft.

Beispiel für die Verwendung

Es gibt ein Beispiel für monkey-Parcheando in der Pandas-Dokumentation:

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

Um dies aufzuschlüsseln, importieren wir zunächst unser Modul:

import pandas as pd

Als nächstes erstellen wir eine Methodendefinition, die ungebunden und frei außerhalb des Geltungsbereichs von Klassendefinitionen existiert (da die Unterscheidung zwischen einer Funktion und einer ungebundenen Methode ziemlich bedeutungslos ist, hat Python 3 die ungebundene Methode abgeschafft):

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]

Als Nächstes fügen wir diese Methode einfach der Klasse zu, in der wir sie verwenden wollen:

pd.DataFrame.just_foo_cols = just_foo_cols # monkey-patch the DataFrame class

Und dann können wir die Methode auf eine Instanz der Klasse anwenden und die Methode löschen, wenn wir fertig sind:

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

Warnung vor Namensverwechslungen

Wenn Sie Namensvermischung verwenden (das Voranstellen von Attributen mit einem doppelten Unterstrich, der den Namen verändert und den ich nicht empfehle), müssen Sie die Namensvermischung manuell durchführen. Da ich die Namensvermischung nicht empfehle, werde ich sie hier nicht demonstrieren.

Beispiel für eine Prüfung

Wie können wir dieses Wissen z. B. bei Prüfungen einsetzen?

Angenommen, wir müssen einen Datenabruf an eine externe Datenquelle simulieren, der zu einem Fehler führt, weil wir in einem solchen Fall ein korrektes Verhalten sicherstellen wollen. Wir können die Datenstruktur mit einem Affenpatch versehen, um dieses Verhalten zu gewährleisten. (Verwenden Sie also einen ähnlichen Methodennamen wie von Daniel Roseman vorgeschlagen:)

import datasource

def get_data(self):
    '''monkey patch datasource.Structure with this to simulate error'''
    raise datasource.DataRetrievalError

datasource.Structure.get_data = get_data

Und wenn wir sie auf ein Verhalten testen, das darauf beruht, dass diese Methode einen Fehler auslöst, erhalten wir dieses Verhalten in den Testergebnissen, wenn es korrekt implementiert ist.

Allein durch die oben genannten Schritte wird die Structure Objekt für die gesamte Dauer des Prozesses. Um dies zu vermeiden, sollten Sie in Ihren Unittests Setups und Teardowns verwenden, z. B.:

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

(Obwohl die obige Vorgehensweise in Ordnung ist, wäre es wahrscheinlich eine bessere Idee, die mock Bibliothek, um den Code zu patchen. mock 's patch Dekorator wäre weniger fehleranfällig als die obige Vorgehensweise, die mehr Codezeilen und damit mehr Möglichkeiten zur Fehlereinführung erfordern würde. Ich muss noch den Code in mock aber ich kann mir vorstellen, dass es monkey-Parcheando auf ähnliche Weise verwendet).

41voto

David Heffernan Punkte 585606

Según Wikipedia :

In Python ist der Begriff Affenpatch nur auf dynamische Änderungen einer Klasse oder eines Moduls zur Laufzeit, motiviert durch die Absicht, bestehenden Code von Drittanbietern als Umgehung eines Fehler oder eine Funktion, die sich nicht wie gewünscht Sie wünschen.

21voto

Andreas Jung Punkte 1

Erstens: Affe Parcheando ist ein böser Hack (meiner Meinung nach).

Sie wird häufig verwendet, um eine Methode auf Modul- oder Klassenebene durch eine eigene Implementierung zu ersetzen.

Der häufigste Anwendungsfall ist das Hinzufügen eines Workarounds für einen Fehler in einem Modul oder einer Klasse, wenn Sie den ursprünglichen Code nicht ersetzen können. In diesem Fall ersetzen Sie den "falschen" Code durch monkey Parcheando mit einer Implementierung innerhalb Ihres eigenen Moduls/Pakets.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X