Können Sie Patch-Methoden auf Kerntypen in Python anwenden?
Ruby hinzufügen können Methoden, um die Number-Klasse und andere core-Typen, die zu erhalten Ergebnisse wie diese:
1.should_equal(1)
Aber es scheint, dass Python nicht. Ist das wahr? Und wenn ja, warum? Hat es etwas mit der Tatsache zu tun, dass Typ nicht geändert werden können?
Update: Anstatt ein Gespräch über unterschiedliche Definitionen von monkey-patching, ich möchte nur auf das Beispiel oben. Ich habe schon festgestellt, dass es nicht getan werden kann, wie ein paar von Euch beantwortet haben. Aber ich würde gerne eine genauere Erklärung, warum es nicht getan werden kann, und vielleicht auch welche Funktion, wenn verfügbar, in Python erlauben würde.
Beantworten einige von Ihnen: Der Grund, warum ich könnte wollen zu tun, das ist einfach ästhetik und Lesbarkeit.
item.price.should_equal(19.99)
Liest sich mehr wie Englisch und zeigt deutlich, die den getesteten Wert und was ist der erwartete Wert, wie es soll:
should_equal(item.price, 19.99)
Diesem Konzept ist, was Rspec und einige andere Ruby-frameworks basieren auf.
InformationsquelleAutor der Frage airportyh | 2008-10-10
Du musst angemeldet sein, um einen Kommentar abzugeben.
Was genau meinst du mit Monkey Patch hier? Es gibt mehrere leicht unterschiedliche Definitionen.
Wenn du meinst, "können Sie ändern, eine Klasse die Methoden zur Laufzeit?", dann ist die Antwort mit Nachdruck: ja:
Wenn du meinst, "können Sie ändern, eine Klasse die Methoden zur Laufzeit und alle Instanzen dieser Klasse ändern, nach-der-Tatsache?" dann ist die Antwort ja auch. Ändern Sie einfach die Reihenfolge leicht:
Aber Sie können nicht tun Sie dies für bestimmte built-in-Klassen, wie
int
oderfloat
. Diese Klassen Methoden implementiert in C und es gibt bestimmte Abstraktionen geopfert, um die Umsetzung zu erleichtern und effizienter zu gestalten.Bin ich nicht wirklich klar, warum Sie möchten, ändern, um das Verhalten der integrierten numerischen Klassen sowieso. Wenn Sie brauchen, um Ihr Verhalten ändern, Unterklasse!!
InformationsquelleAutor der Antwort Dan Lenski
Nein, Sie können nicht. In Python werden alle Daten (Klassen, Methoden, Funktionen, usw.) definiert, die in C-extension Module (einschließlich gelieferten) sind unveränderlich. Dies ist, weil die C-Module werden gemeinsam von mehreren Interpreten im gleichen Prozess, so monkeypatching Sie möchte auch auf unabhängigen Dolmetscher in demselben Prozess.
Aber definierten Klassen in Python-code kann monkeypatched, weil Sie lokal sind, dass der interpreter.
InformationsquelleAutor der Antwort John Millikin
Spaß haben 😉
InformationsquelleAutor der Antwort Jonathan
Können Sie dies tun, aber es dauert ein wenig hacking. Glücklicherweise, gibt es ein Modul nun als "Verbotene Frucht", die Ihnen die macht, um patch-Methoden von built-in Typen sehr einfach. Sie finden ihn unter
http://clarete.github.io/forbiddenfruit/?goback=.gde_50788_member_228887816
oder
https://pypi.python.org/pypi/forbiddenfruit/0.1.0
Mit der ursprünglichen Frage Beispiel, nach der Sie schreiben, die "should_equal" - Funktion, Sie würden einfach tun,
und du bist gut zu gehen! Es gibt auch eine "reverse" - Funktion zum entfernen einer gepatchten Methode.
InformationsquelleAutor der Antwort alcalde
Python-core-Typen sind unveränderlich durch design, als andere Benutzer haben darauf hingewiesen:
Werden Sie sicherlich könnte erreichen den Effekt, den Sie beschreiben, indem Sie eine Unterklasse erstellen, da benutzerdefinierte Typen, die in Python wandelbar ist, standardmäßig.
Gibt es keine Notwendigkeit, um die
MyInt
Unterklasse öffentlichen, entweder; man könnte genauso gut definieren inline direkt in der Funktion oder Methode, die Konstrukte der Instanz.Es gibt sicherlich ein paar Situationen, in denen Python-Programmierer, die fließend in der Sprache betrachten diese Art von Unterklassen, die richtige Sache zu tun. Zum Beispiel
os.stat()
gibt einetuple
Unterklasse fügt hinzu, dass benannte Mitglieder, und zwar genau um die Art von Lesbarkeit sorgen, die Sie finden in Ihrem Beispiel.Sagte, dass, im konkreten Beispiel, das Sie geben, ich glaube nicht, dass Unterklassen
float
imitem.price
(oder anderswo), würde man sehr wahrscheinlich betrachtet werden, die Pythonic, was zu tun. Ich kann sich leicht vorstellen, dass jemand die Entscheidung zum hinzufügen einesprice_should_equal()
Methodeitem
wenn das der primäre Zweck; wenn man waren auf der Suche für etwas allgemeineres, vielleicht macht es mehr Sinn, zu verwenden benannte Argumente, um die beabsichtigte Bedeutung klarer, als inoder etwas entlang jenen Linien. Es ist ein bisschen verbose, aber kein Zweifel, es verbessert werden könnte. Ein möglicher Vorteil solcher Ansatz über Ruby-Stil monkey-patching ist, dass
should_equal()
könnte leicht führen Sie Ihren Vergleich auf jede Art, nicht nurint
oderfloat
. Aber vielleicht bin ich immer zu gefangen in den details der jeweiligen Beispiel, dass Sie zufällig zur Verfügung zu stellen.InformationsquelleAutor der Antwort zaphod
Können Sie nicht, patch-Kern-Typen in python.
Jedoch, Sie könnte verwenden pipe zu schreiben, eine mehr menschenlesbare code:
InformationsquelleAutor der Antwort Lvsoft
Hier ist ein Beispiel der Implementierung
item.price.should_equal
obwohl ich die Decimal anstelle von float in einem echten Programm:InformationsquelleAutor der Antwort Ryan Ginstrom
Wenn Sie wirklich, wirklich wirklich wollen eine monkey patch in Python, die Sie tun können, eine (sortof) hack mit dem "import foo as bar" - Technik.
Wenn Sie eine Klasse wie TelnetConnection, und Sie möchten, um es zu erweitern, Unterklasse, die es in einer separaten Datei und rufen Sie es etwas wie TelnetConnectionExtended.
Dann, oben in deinem code, wo man normalerweise sagen würde:
ändern werden:
und dann überall im code, auf den Sie verweisen TelnetConnection tatsächlich verweisen auf TelnetConnectionExtended.
Leider, dies vorausgesetzt, dass Sie Zugriff auf diese Klasse, und das "wie" funktioniert nur innerhalb der jeweiligen Datei (es ist nicht ein global-umbenennen), aber ich habe festgestellt, dass es nützlich sein, von Zeit zu Zeit.
InformationsquelleAutor der Antwort HanClinto
Nein, leider können Sie nicht verlängern Arten implementiert in C zur Laufzeit.
Können Sie eine Unterklasse int, obwohl es ist nicht trivial, müssen Sie möglicherweise überschreiben
__new__
.Haben Sie auch ein syntax-Problem:
Jedoch
InformationsquelleAutor der Antwort Dima Tisnek
Nein, Sie können das nicht in Python. Ich halte es für eine gute Sache.
InformationsquelleAutor der Antwort sanxiyn
Nein, aber Sie haben UserDict UserString und UserList die gemacht wurden, mit genau diesem im Verstand.
Wenn Sie google, die Sie finden Beispiele für andere Typen, aber diese sind vordefiniert.
Im Allgemeinen monkey-patching ist weniger verwendet, in Python als in Ruby.
InformationsquelleAutor der Antwort Luka Marinko
Was bedeutet
should_equal
tun? Ist es ein boolean zurückgebenTrue
oderFalse
? In diesem Fall ist es geschrieben:Es gibt keine Rechnungslegung für Geschmack, aber keine regelmäßigen python-Entwickler würde sagen, das ist schlechter lesbar als deine version.
Tut
should_equal
stattdessen auf eine Art von Prüfung? (warum sollte ein validator werden auf einen Wert beschränkt? Warum nicht einfach den Wert festlegen und nicht, aktualisieren Sie es nach?) Wenn Sie möchten, eine Prüfung, das könnte nie funktionieren eh, da bist du vorschlagen zu ändern, entweder eine bestimmte Zahl oder alle zahlen. (Eine Prüfung, die erfordert, dass18.99
gleich19.99
wird immer scheitern.) Stattdessen könnten Sie schreiben es so:oder so:
und definieren geeignete Methoden, die auf Element-Klasse oder Oberklassen.
InformationsquelleAutor der Antwort
Es scheint, was Sie eigentlich schreiben wollte ist:
(Natürlich vergleicht man schwebt für die Gleichstellung, oder mit Schwimmern für die Preise, ist eine schlechte Ideeso würden Sie schreiben
assert item.price == Decimal(19.99)
oder was auch immer Klasse numeric, Sie wurden mit für den Preis.)Können Sie auch ein Test-framework wie py.test um mehr Infos zu bekommen, die auf Versäumnis geltend macht, die in Ihren tests.
InformationsquelleAutor der Antwort Petr Viktorin
Hier, wie ich erreichen .should_something... Verhalten:
oder
Habe ich eine decorator-Methode für die Verlängerung dieses Verhalten zur Laufzeit auf einen stand-alone-Methode:
Müssen Sie wissen, ein wenig über die Interna, aber es funktioniert.
Hier ist die Quelle:
https://github.com/mdwhatcott/pyspecs
Ist es auch auf PyPI unter pyspecs.
InformationsquelleAutor der Antwort mdwhatcott