基于字符串repr获取对象的实例(Python)

时间:2012-06-13 15:42:58

标签: python

  

可能重复:
  Python: Get object by id

通常,当您看到实例的字符串表示时,它看起来像<module.space.Class @ 0x108181bc>。我很好奇是否可以获取该字符串并获取实例的句柄。

这样的东西
 obj_instance = get_instance_form_repr("<module.space.Class @ 0x1aa031b>")

我不相信这是可能的,但如果确实如此,那将非常有用。

2 个答案:

答案 0 :(得分:2)

至少可以以恶劣且不可靠的方式为垃圾收集器跟踪的子集执行此操作。

def lookup_object_by_repr(myrep)
    import gc
    for obj in gc.get_objects():
        if repr(obj) == myrep:
           return obj

如果你编写一个简单的C扩展并检查内存地址,你可以做更多的事情。

答案 1 :(得分:1)

当然没有办法从它的repr中获取一个对象,因为任何类都可以在它的repr中返回它想要的任何东西。但是在repr中有指针的特定情况下,你基本上是在询问如何从指针中获取对象。哪个(至少在C Python中)与询问如何从其id获取对象完全相同。

没有内置的方法可以做到这一点,即使它非常简单。这是故意的,因为这几乎总是一个坏主意。

如果您认为通过id获取对象有实际目的,那么您可能错了。特别是因为您必须处理通常自动处理的对象生命周期问题(并且在您的背后,这使得即使您尝试也很难手动处理它们)。例如,如果一个对象消失,那个对象的弱参数会空出来,但是id仍然指向释放的内存,或者稍后创建的另一个对象,或者一个对象的一半和另一个对象的一半。当然,无论你在C Python中做什么都不能在PyPy或jython或IronPython中运行......

但是如果你只是在修补C Python运行时的工作方式,那么这是一个合理的问题,并且有一个合理的答案。可能最好的方法是创建一个C扩展模块。如果你不知道如何创建一个扩展模块,你真的应该先学习,然后再回到这个问题。如果这样做,您要实现的功能非常简单:

static PyObject *objectFromId(PyObject *self, PyObject *args) {
  PyObject *obj;
  if (!PyArg_ParseTuple(args, "n", &obj)) return NULL;
  Py_INCREF(obj);
  return obj;
}

如果你愿意的话,你可以在Pyrex / Cython而不是C中这样做。或者你可以直接在_ctypes模块上调用PyObj_FromPtr。但是如果你试图了解这个层面的工作原理,那么让发生的事情变得明确更有意义,并明确地将你的“处理C指针”代码放在C中。

进一步思考,你想建立一种最好的猜测objectFromRepr用于修补目的,你可以。基本上是:

  • 使用与普通角括号格式匹配的正则表达式;如果匹配,请使用地址调用objectFromId。
  • 致电评估。

您可能希望在其中放置一个中间步骤:对于许多类型,repr采用类似于(Arg1,arg2)的构造函数调用的形式,在这种情况下,将该表单与另一个表单匹配可能更好正则表达式并直接调用构造函数,而不是使用eval。如果不出意外,它可能更有启发性,这就是这个练习的重点,对吗?

显然,在现实代码中,这比objectFromId更加糟糕。使用eval几乎总是坏的,并且eval(repr(x))== x实际上并不保证是真的,并且你实际上在id情况下获得了对同一个对象的新引用,但是在eval案例中的值相同,并且......

PS,在你了解了所有这些在C Python中是如何工作之后,可能值得在另一个解释器(如jython或IronPython)中进行类似的练习(特别是当你重新编写本机Java / .NET / etc。对象时)。 p>