10

出于特定调试目的,我想包装任意对象的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

4 回答 4

8

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

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

这是基于我为另一个问题编写的通用函数的解决方案: 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
于 2011-05-15T19:50:21.577 回答
1

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

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

此外,some_object.__del__ 根本不保证被调用

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

于 2011-05-15T19:54:47.363 回答
0

您还可以从某些基类继承并覆盖该__del__方法(那么您只需要在构造对象时覆盖类)。或者您可以使用super内置方法。

于 2011-05-15T18:25:37.477 回答
0

编辑:这实际上不起作用,我把它留在这里主要是作为对其他人的警告。

您可以猴子修补单个对象。self不会以这种方式传递给你猴子修补的函数,但这很容易用functools.partial.

例子:

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

def monkey_object(x):
    x.__del__ = functools.partial(p, x)
于 2011-05-15T19:02:33.887 回答