【问题标题】:Tracking object allocation in python在 python 中跟踪对象分配
【发布时间】:2011-01-25 18:29:45
【问题描述】:

是否有任何方法可以让我使用打印语句/pdb/等来跟踪每次分配我的类的实例?在解开一些对象时,我似乎得到了一些从未调用过__setstate____init__ 的对象。我尝试覆盖__new__ 并打印出我在__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。

【问题讨论】:

  • 你确定它们是不同的实例吗?你检查过id(instance) 是否匹配?
  • 您是否尝试使用Allocator(cls) 作为类型转换?如果是这样,那就错了,因为在 Python 中它是对 Allocator 对象的构造函数调用,而 .new 部分将获得一个新的绑定方法实例。
  • 罗什:是的。我的分配器函数显示了我打印出 id(instance) 的方式。后来,当我发现一个对象缺少一些应该由 setstate 或 init 添加的字段时,我也打印出它的 id。如果我在之前的打印输出中 grep 获取该 ID,则没有命中。
  • Apalala:我确实打算使用Allocator(cls) 作为Allocator 对象的构造函数调用。用cls构造的Allocator的意义在于调用cls原来的__new__方法,并报告得到的对象实例的id
  • 迭代应该是for parent in cls.__bases__。您不需要回退到cls.__base__。并且不要使用包罗万象的except: 子句。他们总是咬你。

标签: python allocation creation


【解决方案1】:

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

引用 Guido 的 Unifying types and classes in Python 2.2:

在某些情况下创建新实例而不调用__init__(例如,从泡菜加载实例时)。不调用 __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>

【讨论】:

  • 这听起来像是一种可行的方法,但不幸的是,如果您可以不调用基类,那么这可能解释了为什么在我不知情的情况下分配了对象。我只允许为 object 本身以外的类覆盖 __new__
【解决方案2】:

你在使用新式的类吗?为了让 Pickle 调用 __setstate____getstate__ 方法也应该在类 returning a non-False value 上定义。

【讨论】:

  • 这并没有回答如何在创建对象时检测对象的问题。但是是的,我正在使用新型类,并且确实实现了__getstate__。此外,__setstate__ 会在该类的大多数但不是所有实例上被调用。
【解决方案3】:

不确定这是否可以帮助您,但 Python 的垃圾收集器有 introspective capabilities 可能值得一看。

【讨论】:

  • 问题是关于跟踪对象的创建
  • 你说得对,我很可能误解了这个问题。但是现在我想知道,垃圾收集器不需要自己来监控对象分配吗?如果是这样,人们可能会设计一种方法来挂钩 gc 并找出感兴趣的对象何时被分配。我不是在质疑你说的,我只是好奇。
猜你喜欢
  • 1970-01-01
  • 2011-11-07
  • 2012-12-16
  • 1970-01-01
  • 1970-01-01
  • 2015-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多