有什么方法可以从弱代理中获取原始对象吗?例如,weakref.proxy()是否有反函数?
一个简化的例子(python2.7):

import weakref

class C(object):
    def __init__(self, other):
        self.other = weakref.proxy(other)

class Other(object):
    pass

others = [Other() for i in xrange(3)]

my_list = [C(others[i % len(others)]) for i in xrange(10)]

我需要从other获得唯一的my_list成员的列表。我喜欢此类任务的方式
是使用set:
unique_others = {x.other for x in my_list}

不幸的是,这引发了TypeError: unhashable type: 'weakproxy'我设法以命令式的方式解决了特定的问题(缓慢而肮脏):
unique_others = []
for x in my_list:
    if x.other in unique_others:
        continue
    unique_others.append(x.other)

但是标题中指出的一般问题仍然有效。
如果我只控制my_listothers到某个库中,并且有人可以随时删除它们,又想通过在列表中收集 nonweak 引用来防止删除,该怎么办?
或者我可能想获取对象本身的repr(),而不是<weakproxy at xx to Other at xx>我猜应该有我不知道的类似weakref.unproxy的东西。

最佳答案

基本上有类似weakref.unproxy的东西,但它只是命名为weakref.ref(x)()
代理对象仅用于委派,实现相当不稳定。
==函数无法正常运行:

>>> weakref.proxy(object) == object
False
>>> weakref.proxy(object) == weakref.proxy(object)
True
>>> weakref.proxy(object).__eq__(object)
True

但是,我看到您不想一直调用weakref.ref对象。一个具有解除引用支持的良好工作代理将是不错的选择。

但是目前,这是不可能的。如果您查看python内置的源代码,则需要像PyWeakref_GetObject这样的东西,但根本没有对该方法的调用(并且:如果参数错误,它将引发一个PyErr_BadInternalCall,因此它似乎是一个内部函数)。 PyWeakref_GET_OBJECT的使用更多,但是weakref.py中没有能够做到这一点的方法。

因此,很抱歉让您失望,但是weakref.proxy并不是大多数人想要的用例。但是,您可以创建自己的proxy实现。这并不难。只需在内部使用weakref.ref并覆盖__getattr____repr__等即可。

关于PyCharm如何能够产生正常的repr输出的一点说明(因为您在注释中提到了这一点):
>>> class A(): pass
>>> a = A()
>>> weakref.proxy(a)
<weakproxy at 0x7fcf7885d470 to A at 0x1410990>
>>> weakref.proxy(a).__repr__()
'<__main__.A object at 0x1410990>'
>>> type( weakref.proxy(a))
<type 'weakproxy'>

如您所见,调用原始的__repr__确实有帮助!

10-08 07:13