【问题标题】:Obtaining an object's instance based on its string repr (Python) [duplicate]根据字符串 repr 获取对象的实例(Python)[重复]
【发布时间】:2012-06-13 15:42:57
【问题描述】:

可能重复:
Python: Get object by id

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

类似

 obj_instance = get_instance_form_repr("<module.space.Class @ 0x1aa031b>")

我不相信这是可能的,但如果是的话,它会非常有用。

【问题讨论】:

  • 出于兴趣,您为什么要这样做?它在您的代码中响起其他问题。
  • 正如该答案所暗示的,像这样的对象查找唯一可能的用途是通用弱图实现。 Python 支持弱引用,所以它实际上没用,除非你有其他想法?
  • 任何代码都不是问题,我只是好奇它是否可能。从纯粹的修补的角度来看。

标签: python


【解决方案1】:

您至少可以为垃圾收集器跟踪的子集以一种令人讨厌且不可靠的方式这样做。

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

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

【讨论】:

  • 好点。对于修补或几乎任何其他目的,C 扩展可能是一个更好的解决方案——但这个实际上是尽可能接近 repr 函数的真正逆。
【解决方案2】:

当然,没有办法从它的 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 采用构造函数调用的形式,例如 Class(arg1, arg2),在这种情况下,最好将该形式与另一个匹配正则表达式并直接调用构造函数,而不是使用 eval。如果不出意外,它可能更有启发性,这就是本练习的重点,对吧?

显然,在实际代码中,这比 objectFromId 更糟糕。使用 eval 几乎总是不好的,并且 eval(repr(x)) == x 实际上并不能保证为真,并且您实际上在 id 情况下获得了对同一对象的新引用,但新对象带有eval 情况下的值相同,并且…

PS,在您了解了所有这些在 C Python 中的工作原理之后,可能值得在另一个解释器(如 jython 或 IronPython)中进行类似的练习(尤其是当您表示本机 Java/.NET/etc. 对象时)。

【讨论】:

    猜你喜欢
    • 2020-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-30
    • 1970-01-01
    • 2013-06-13
    • 1970-01-01
    相关资源
    最近更新 更多