13

それを指すweakproxyから元のオブジェクトを取得する方法はありますか? たとえば、の逆はあり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_list制御下にあるだけでothers、いくつかのライブラリに埋もれていて、誰かがいつでもそれらを削除する可能性があり、リスト内の非弱い参照を収集して削除を防ぎたい場合はどうすればよいですか?

repr()または、オブジェクト自体の を取得したい場合があります。<weakproxy at xx to Other at xx>

weakref.unproxy私が気づいていない ようなものがあるはずだと思います。

4

4 に答える 4

8

基本的にはのようなものがありますが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、引数が間違っている場合はaが発生するため、内部関数のようです) 。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__を呼び出すと非常に役立ちます。

于 2012-08-12T09:26:00.030 に答える
3

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_list には、根本的に異なるrefs ではなくproxys が含まれるようになりました...

于 2012-04-20T13:29:36.500 に答える