跟踪Python中的对象分配
有没有什么方法可以让我重写某个函数,这样我就可以使用打印语句、调试工具等,来跟踪每次我的类的实例被创建时的情况?在反序列化一些对象时,我发现有些对象的 __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>