猴子补丁__del__到新功能

Ger*_*nuk 10 python monkeypatching

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

理想情况下,我想编写monkey(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
Run Code Online (Sandbox Code Playgroud)

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

谁知道如何实现?

Boa*_*niv 8

虽然特殊的"双下划线"的方法,如__del__,__str__,__repr__,等均可猴子打补丁的情况下的水平,他们就会被忽略,除非它们被直接(例如,如果你把五花八门的答案:del a将不打印的东西,但a.__del__()会).

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

这是一个基于我为另一个问题写的泛型函数的解决方案: Python方法解析之谜

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
Run Code Online (Sandbox Code Playgroud)

  • 新类派生自旧类 - 所以是的,它已经有了相同的超类.只要用`isinstance(x,C)`检查类,而不用`type(x)== C`(你通常不应该这样做),一切都会好的. (3认同)
  • 这种方法存在两个问题:首先,它不适用于像int或list这样的堆类型,因为你不能重新分配它们的`__class__`.其次,类型检查会导致不同的结果,具体取决于对象是否为猴子().这可能会导致非常混乱的错误. (2认同)