Python:解除对weakproxy的引用
有没有办法从指向原始对象的弱路径获取原始对象?例如,weakref.proxy()是否与Python:解除对weakproxy的引用,python,weak-references,Python,Weak References,有没有办法从指向原始对象的弱路径获取原始对象?例如,weakref.proxy()是否与相反 一个简化示例(python2.7): 我需要从我的列表中获取唯一其他成员的列表。我喜欢这样的工作方式 要使用设置: unique_others = {x.other for x in my_list} 不幸的是,这会抛出TypeError:unhabable类型:“weakproxy” 我已设法以一种紧迫的方式(缓慢而肮脏)解决了具体问题: 但标题中指出的一般问题仍然存在。 如果我只控制了我的列表,而
相反
一个简化示例(python2.7):
我需要从我的列表
中获取唯一其他
成员的列表。我喜欢这样的工作方式
要使用设置
:
unique_others = {x.other for x in my_list}
不幸的是,这会抛出TypeError:unhabable类型:“weakproxy”
我已设法以一种紧迫的方式(缓慢而肮脏)解决了具体问题:
但标题中指出的一般问题仍然存在。
如果我只控制了我的列表
,而其他的
则埋在一些库中,有人可以随时删除它们,我想通过收集列表中的非弱引用来防止删除,那该怎么办
或者我可能想要获取对象本身的repr()
,而不是
我想应该有类似于weakref.unproxy
的东西我不知道。weakref.ref是可散列的,而weakref.proxy不是。API没有说明如何实际获取代理指向的对象的句柄。有了weakref,这很容易,你可以直接打电话给它。因此,您可以滚动自己的代理类…下面是一个非常基本的尝试:
import weakref
class C(object):
def __init__(self,obj):
self.object=weakref.ref(obj)
def __getattr__(self,key):
if(key == "object"): return object.__getattr__(self,"object")
elif(key == "__init__"): return object.__getattr__(self,"__init__")
else:
obj=object.__getattr__(self,"object")() #Dereference the weakref
return getattr(obj,key)
class Other(object):
pass
others = [Other() for i in range(3)]
my_list = [C(others[i % len(others)]) for i in range(10)]
unique_list = {x.object for x in my_list}
当然,现在unique_列表包含ref
s,而不是proxy
s,这是根本不同的…基本上有类似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内置源代码,您会发现,您需要类似的东西,但根本没有对该方法的调用(并且:如果参数错误,它会引发PyErr\u BadInternalCall
,因此它似乎是一个内部函数)。使用得更多,但没有一种方法可以做到这一点
所以,很抱歉让您失望,但是您weakref.proxy
并不是大多数人想要的用例。但是,您可以创建自己的代理
实现。这并不难。只需在内部使用weakref.ref
,并覆盖\uuu getattr\uuuu
、\uu repr\uuu
等
关于PyCharm如何生成正常的repr
输出的一点旁注(因为您在评论中提到了这一点):
>A类():通过
>>>a=a()
>>>weakref.代理(a)
>>>weakref.proxy(a)。_urepr_______;
''
>>>类型(weakref.proxy(a))
正如您所看到的,调用原始的
\uuuu repr\uuu
确实有帮助 我知道这是一个老问题,但我最近在寻找答案,并想出了一些办法。正如其他人所说,没有文档化的方法可以做到这一点,查看weakproxy类型的实现可以确认,没有标准的方法可以实现这一点
我的解决方案使用了这样一个事实:所有Python对象都有一组标准方法(如\uuuu repr\uuu),绑定的方法对象包含对实例的引用(在\uu self\uu属性中)
因此,通过取消对代理的引用以获取方法对象,我们可以从方法对象获得对代理对象的强引用
例如:
>>> def func():
... pass
...
>>> weakfunc = weakref.proxy(func)
>>> f = weakfunc.__repr__.__self__
>>> f is func
True
另一件好事是,它也适用于强引用:
>>> func.__repr__.__self__ is func
True
因此,如果需要代理或强引用,则不需要进行类型检查
编辑:
我只是注意到这不适用于类的代理。这不是一个普遍的问题。我知道这是一个老问题,但我已经被它咬了一口(因此,标准库中没有真正的“不稳定”),我想分享我的解决方案 我解决它以获得真实实例的方法只是创建一个返回它的属性(尽管我建议使用
weakref.ref
而不是weakref.proxy
,因为代码应该在访问它之前真正检查它是否仍然处于活动状态,而不是在访问任何属性时都必须记住捕获异常)
无论如何,如果您仍然必须使用代理,那么获取真实实例的代码是:
import weakref
class MyClass(object):
@property
def real_self(self):
return self
instance = MyClass()
proxied = weakref.proxy(instance)
assert proxied.real_self is instance
API没有,但是像PyCharm这样的IDE能够以某种方式在监视列表窗口中显示repr()的结果。@robyschek当然有可能。我相信您可以在标准库的某个地方找到代码,并找出代理对象是如何工作的……但是如果API中没有对其进行记录,您就不能保证它可以移植到其他python实现中。。。
>>> def func():
... pass
...
>>> weakfunc = weakref.proxy(func)
>>> f = weakfunc.__repr__.__self__
>>> f is func
True
>>> func.__repr__.__self__ is func
True
import weakref
class MyClass(object):
@property
def real_self(self):
return self
instance = MyClass()
proxied = weakref.proxy(instance)
assert proxied.real_self is instance