问题
For specific debugging purposes I'd like to wrap the del function of an arbitrary object to perform extra tasks like write the last value of the object to a file.
Ideally I want to write monkey(x) and it should mean that the final value of x is printed when x is deleted
Now I figured that del is a class method. So the following is a start:
class Test:
def __str__(self):
return "Test"
def p(self):
print(str(self))
def monkey(x):
x.__class__.__del__=p
a=Test()
monkey(a)
del a
However if I want to monkey specific objects only I suppose I need to dynamically rewrite their class to a new one?! Moreover I need to do this anyway, since I cannot access del of built-in types?
Anyone knows how to implement that?
回答1:
While special 'double underscore' methods like __del__
, __str__
, __repr__
, etc. can be monkey-patched on the instance level, they'll just be ignored, unless they are called directly (e.g., if you take Omnifarious's answer: del a
won't print a thing, but a.__del__()
would).
If you still want to monkey patch a single instance a
of class A
at runtime, the solution is to dynamically create a class A1
which is derived from A
, and then change a
's class to the newly-created A1
. Yes, this is possible, and a
will behave as if nothing has changed - except that now it includes your monkey patched method.
Here's a solution based on a generic function I wrote for another question: Python method resolution mystery
def override(p, methods):
oldType = type(p)
newType = type(oldType.__name__ + "_Override", (oldType,), methods)
p.__class__ = newType
class Test(object):
def __str__(self):
return "Test"
def p(self):
print(str(self))
def monkey(x):
override(x, {"__del__": p})
a=Test()
b=Test()
monkey(a)
print "Deleting a:"
del a
print "Deleting b:"
del b
回答2:
You can also inherit from some base class and override the __del__
method (then only thing you would need would be to override class when constructing an object).
Or you can use super
built-in method.
回答3:
del a
deletes the name 'a' from the namespace, but not the object referenced by that name. See this:
>>> x = 7
>>> y = x
>>> del x
>>> print y
7
Also, some_object.__del__
is not guaranteed to be called at all.
Also, I already answered your question here (in german).
回答4:
Edit: This won't actually work, and I'm leaving it here largely as a warning to others.
You can monkey patch an individual object. self
will not get passed to functions that you monkey patch in this way, but that's easily remedied with functools.partial
.
Example:
def monkey_class(x):
x.__class__.__del__ = p
def monkey_object(x):
x.__del__ = functools.partial(p, x)
来源:https://stackoverflow.com/questions/6010282/monkey-patch-del-to-new-function