猴子补丁__del__到新功能

时间:2011-05-15 18:17:33

标签: python monkeypatching

出于特定的调试目的,我想包装任意对象的 del 函数来执行额外的任务,比如将对象的最后一个值写入文件。

理想情况下我想写     猴子(X) 它应该意味着当x被删除时打印x的最终值

现在我认为 del 是一种类方法。所以以下是一个开始:

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

但是,如果我想要特定对象,我想我需要动态地将它们的类重写为新类?此外,我还需要这样做,因为我无法访问内置类型的 del

任何人都知道如何实现它?

4 个答案:

答案 0 :(得分:7)

虽然__del____str____repr__等特殊的“双下划线”方法可以在实例级别进行猴子修补,但它们只会被忽略,除非它们被称为直接(例如,如果你采用Omnifarious的回答:del a将不打印任何东西,但a.__del__()会。)

如果您仍希望在运行时修补类a单实例 A,则解决方案是动态创建类A1,这是派生自A,然后将a的类更改为新创建的A1。是的,这是可能的,a的行为就好像什么都没有改变 - 除了现在它包括你的猴子补丁方法。

这是基于我为另一个问题写的通用函数的解决方案: 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

答案 1 :(得分:0)

您也可以从某个基类继承并覆盖__del__方法(然后在构造对象时,您只需要覆盖类)。 或者您可以使用super内置方法。

答案 2 :(得分:0)

您可以修补单个对象。 self不会以这种方式传递给您修补的函数,但使用functools.partial可以很容易地解决这个问题。

示例:

def monkey_class(x):
    x.__class__.__del__ = p

def monkey_object(x):
    x.__del__ = functools.partial(p, x)

答案 3 :(得分:0)

del a从命名空间中删除名称“a”,但不删除该名称引用的对象。见:

>>> x = 7
>>> y = x
>>> del x
>>> print y
7

此外,some_object.__del__ is not guaranteed to be called at all

另外,我已经回答了你的问题here(德语)。