Monkey patch __del__ to new function

谁说胖子不能爱 提交于 2019-12-06 20:14:44

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!