跟踪Python中的对象分配

10 投票
3 回答
1591 浏览
提问于 2025-04-16 10:36

有没有什么方法可以让我重写某个函数,这样我就可以使用打印语句、调试工具等,来跟踪每次我的类的实例被创建时的情况?在反序列化一些对象时,我发现有些对象的 __setstate____init__ 方法从来没有被调用过。我尝试重写 __new__ 方法,并在其中打印出每个对象的 ID,但我仍然遇到了一些 ID 从未被打印出来的对象。

编辑:这是我用来修改(插入调试代码)我类的 __new__ 方法以及它所有父类的方法(除了 object 本身)的代码:

class Allocator:
    def __init__(self, my_class):
       self.my_class = my_class
       self.old_new = my_class.__new__

    def new(self, * args, ** kargs):
        rval = self.old_new(*args, ** kargs)
        #rval = super(self.my_class,cls).__new__(cls)
        print 'Made '+str(self.my_class)+' with id '+str(id(rval))
        return rval

def replace_allocator(cls):
    if cls == object:
        return

    setattr(cls,'__new__',Allocator(cls).new)
    print cls.__base__

    try:
        for parent in cls.__base__:
            replace_allocator(parent)
   except:
        replace_allocator(cls.__base__)

我在主脚本中导入类的父类后,立即调用了 replace_allocator。我这个类本身就有一个自定义的 __new__ 方法,它也会打印出对象的 ID。

3 个回答

0

你在使用新式类吗?为了让 Pickle 调用 __setstate__ 方法,你的类里也应该定义 __getstate__ 方法,并且这个方法要返回一个不是 False 的值。

0

不确定这是否能帮到你,但Python的垃圾回收器有一些自我检查的功能,可能值得你去了解一下。

5

(这更像是一个评论,而不是答案。)

引用Guido在Python 2.2中统一类型和类的内容:

有些情况下,创建一个新实例时并不会调用__init__(比如当实例是从一个pickle文件加载时)。但是,没有办法在不调用__new__的情况下创建一个新实例(虽然在某些情况下,你可以通过调用基类的__new__来实现)。

如果你使用的是新式类(也就是从object派生的类),那么__new__()应该总是被调用。我认为那些“你可以通过调用基类的__new__来实现”的特殊情况不会意外发生,不过我也不知道这些特殊情况具体是什么。

再补充一个例子:

In [1]: class A(object):
   ...:     def __new__(cls):    
   ...:         print "A"
   ...:         return object.__new__(cls)
   ...:     

In [2]: A()
A
Out[2]: <__main__.A object at 0xa3a95cc>

In [4]: object.__new__(A)
Out[4]: <__main__.A object at 0xa3a974c>

撰写回答