Die erste Sache zu beachten ist, dass was auch immer forbiddenfruit
tut, hat es keinen Einfluss repr
überhaupt. Dies ist kein Sonderfall für str
, es funktioniert einfach nicht so:
import gc
underlying_dict = gc.get_referents(str.__dict__)[0]
underlying_dict["__repr__"] = lambda self: print("I am a str!")
"hello".__repr__()
#>>> I am a str!
repr("hello")
#>>> "'hello'"
So wissen wir, etwas anticlimactically:
import forbiddenfruit
class X:
repr = None
repr(X())
#>>> '<X object at 0x7f907acf4c18>'
forbiddenfruit.curse(X, "__repr__", lambda self: "I am X")
repr(X())
#>>> '<X object at 0x7f907acf4c50>'
X().__repr__()
#>>> 'I am X'
X.__repr__ = X.__repr__
repr(X())
#>>> 'I am X'
ich a much simpler way of doing what forbiddenfruit
does dank einem Beitrag von HYRY kürzlich gefunden , dass etwas anderes vor sich geht.
Hier the source for builtin_repr
:
builtin_repr(PyModuleDef *module, PyObject *obj)
/*[clinic end generated code: output=988980120f39e2fa input=a2bca0f38a5a924d]*/
{
return PyObject_Repr(obj);
}
Und für PyObject_Repr
(Abschnitte elided):
PyObject *
PyObject_Repr(PyObject *v)
{
PyObject *res;
res = (*v->ob_type->tp_repr)(v);
if (res == NULL)
return NULL;
}
Der wichtige Punkt ist, dass anstelle von eng g in einem dict
, es sucht das "im Cache gespeicherte" tp_repr
Attribut.
Here's what happens, wenn Sie setzen Sie das Attribut mit so etwas wie TYPE.__repr__ = new_repr
:
static int
type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
{
if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
PyErr_Format(
PyExc_TypeError,
"can't set attributes of built-in/extension type '%s'",
type->tp_name);
return -1;
}
if (PyObject_GenericSetAttr((PyObject *)type, name, value) < 0)
return -1;
return update_slot(type, name);
}
Der erste Teil ist das, was Sie von modifizierenden eingebauten Typen zu verhindern. Dann setzt es das Attribut generisch (PyObject_GenericSetAttr
) und aktualisiert die Slots entscheidend.
Wenn Sie interessiert sind, wie das funktioniert, it's available here.Die entscheidenden Punkte sind:
so replizieren würde es sich Hacker in die PyTypeObject
Art erfordern.
Wenn Sie dies tun möchten, wäre wahrscheinlich die einfachste Sache zu versuchen wäre (vorübergehend?) type->tp_flags & Py_TPFLAGS_HEAPTYPE
auf der str
Klasse. Damit könnte das Attribut normal gesetzt werden. Natürlich gibt es keine Garantie, dass dies Ihren Interpreter nicht zum Absturz bringt.
Dies ist nicht, was ich tun möchte (vor allem nicht durch ctypes
), es sei denn, ich muss wirklich, so biete ich Ihnen eine Verknüpfung.
Sie schreiben:
Dann, wie würden Sie das erwartete Verhalten zu erhalten tun:
>>> 'foo'
'bar'
Das ist eigentlich ganz einfach sys.displayhook
mit:
sys.displayhook
ist aufgerufen auf das Ergebnis der Auswertung einer expression in einer Interaktion eingegeben ive Python-Sitzung. Die Anzeige dieser Werte kann angepasst werden, indem sys.displayhook
eine weitere Einargumentfunktion zugewiesen wird.
Und hier ist ein Beispiel:
import sys
old_displayhook = sys.displayhook
def displayhook(object):
if type(object) is str:
old_displayhook('bar')
else:
old_displayhook(object)
sys.displayhook = displayhook
Und dann ...
'foo'
#>>> 'bar'
123
#>>> 123
Auf dem philosophischen Punkt warumrepr
würde als so zwischengespeichert werden (!) , zuerst betrachten:
1 + 1
Es wäre ein Schmerz, wenn dies __add__
in einem Wörterbuch vor dem Aufruf nachschlagen müsste, CPython ist langsam wie es ist, so CPython entschieden, Lookups nach Standard-Dunder (Doppel-Unterstrich) Methoden zu cachen. __repr__
ist eine davon, auch wenn es weniger üblich ist, dass die Suche optimiert wird. Dies ist immer noch nützlich, um die Formatierung ('%s'%s
) schnell zu halten.
Welches Problem versuchen Sie zu lösen (wodurch Sie die integrierten Methoden überladen möchten)? – goncalopp
mögliches Duplikat von [Überschreiben spezieller Methoden auf einer Instanz] (http://stackoverflow.com/questions/10376604/overriding-special-methods-on-an-instance) – njzk2
@goncalopp: Was ich versuche zu tun ist zu Habe eine laufende Python-Shell, in der der für eine beliebige Zeichenfolge aufgerufene __repr__ durch eine eigene Methode ersetzt wurde. Es muss nicht im qny-Programm verwendet werden, das auf einem anderen Python-Interpreter ausgeführt werden muss. Wie gesagt, Monkey-Patchen meiner eigenen Python wäre in Ordnung, wenn ich nur die Art und Weise kenne, wie ich das machen könnte. – Centime