Python:取消引用弱代理 [英] Python: dereferencing weakproxy

查看:29
本文介绍了Python:取消引用弱代理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法从指向它的弱代理中获取原始对象?例如,是否与 weakref.proxy() 相反?

一个简化的例子(python2.7):

导入弱引用C类(对象):def __init__(self, other):self.other = weakref.proxy(other)类其他(对象):经过其他 = [Other() for i in xrange(3)]my_list = [C(others[i % len(others)]) for i in xrange(10)]

我需要从 my_list 获取唯一的 other 成员列表.我喜欢这样的任务的方式是使用 set:

unique_others = {x.other for x in my_list}

不幸的是,这会抛出 TypeError: unhashable type: 'weakproxy'

我已经设法以一种命令式的方式(缓慢而肮脏)解决了特定问题:

unique_others = []对于 my_list 中的 x:如果 x.other 在 unique_others 中:继续unique_others.append(x.other)

但标题中指出的一般问题仍然存在.如果我只控制了my_list,而others被埋在某个lib中,有人可以随时删除它们,我想通过收集来防止删除怎么办列表中的非弱 引用?

或者我可能想要获取对象本身的 repr(),而不是

我想应该有类似 weakref.unproxy 我不知道的东西.

解决方案

基本上有类似 weakref.unproxy 的东西,但它只是命名为 weakref.ref(x)()代码>.代理对象仅用于委托,并且实现相当不稳定......

== 函数无法正常工作:

<预><代码>>>>weakref.proxy(object) == 对象错误的>>>weakref.proxy(object) == weakref.proxy(object)真的>>>weakref.proxy(object).__eq__(object)真的

但是,我发现您不想一直调用 weakref.ref 对象.具有取消引用支持的良好工作代理会很好.

但目前,这是不可能的.如果你查看你看到的 python 内置源代码,你需要类似 PyWeakref_GetObject,但是根本没有调用此方法(并且:如果参数错误,它会引发 PyErr_BadInternalCall ,因此它似乎是一个内部函数).PyWeakref_GET_OBJECT用的比较多,但是weakref.py 可以做到这一点.

所以,很抱歉让您失望,但是您weakref.proxy 并不是大多数人想要的用例.但是,您可以制作自己的代理实现.这并不难.只需在内部使用 weakref.ref 并覆盖 __getattr____repr__

关于 PyCharm 如何能够产生正常的 repr 输出的一点旁注(因为你在评论中提到了这一点):

<预><代码>>>>A类():通过>>>a = A()>>>弱引用代理(a)<0x7fcf7885d470 处的弱代理到 0x1410990 处的 A>>>>weakref.proxy(a).__repr__()'<__main__.A 对象在 0x1410990>'>>>类型(weakref.proxy(a))<输入'弱代理'>

如您所见,调用原始的 __repr__ 真的很有帮助!

Is there any way to get the original object from a weakproxy pointed to it? eg is there the inverse to weakref.proxy()?

A simplified example(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)]

I need to get the list of unique other members from my_list. The way I prefer for such tasks is to use set:

unique_others = {x.other for x in my_list}

Unfortunately this throws TypeError: unhashable type: 'weakproxy'

I have managed to solve the specific problem in an imperative way(slow and dirty):

unique_others = []
for x in my_list:
    if x.other in unique_others:
        continue
    unique_others.append(x.other)

but the general problem noted in the caption is still active. What if I have only my_list under control and others are burried in some lib and someone may delete them at any time, and I want to prevent the deletion by collecting nonweak refs in a list?

Or I may want to get the repr() of the object itself, not <weakproxy at xx to Other at xx>

I guess there should be something like weakref.unproxy I'm not aware about.

解决方案

Basically there is something like weakref.unproxy, but it's just named weakref.ref(x)(). The proxy object is only there for delegation and the implementation is rather shaky...

The == function doesn't work as you would expect it:

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

However, I see that you don't want to call weakref.ref objects all the time. A good working proxy with dereference support would be nice.

But at the moment, this is just not possible. If you look into python builtin source code you see, that you need something like PyWeakref_GetObject, but there is just no call to this method at all (And: it raises a PyErr_BadInternalCall if the argument is wrong, so it seems to be an internal function). PyWeakref_GET_OBJECT is used much more, but there is no method in weakref.py that could be able to do that.

So, sorry to disappoint you, but you weakref.proxy is just not what most people would want for their use cases. You can however make your own proxy implementation. It isn't to hard. Just use weakref.ref internally and override __getattr__, __repr__, etc.

On a little sidenote on how PyCharm is able to produce the normal repr output (Because you mentioned that in a comment):

>>> 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'>

As you can see, calling the original __repr__ can really help!

这篇关于Python:取消引用弱代理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆