概要
前回の補足メモ。
弱参照を作った際、python データモデルでは、オブジェクトの __weakref__
属性に
設定されるとのこと。試してみると
set01 = {1, 2} wref = weakref.ref(set01) print(hasattr(set01, '__weakref__'))
出力結果は
False
存在しないじゃんって思ったら、これはユーザ定義クラスのみに存在する属性なのですね。
class A: pass a = A() wref = weakref.ref(a) print(hasattr(a, '__weakref__'))
出力結果は
True
この属性は、ユーザ定義クラスにて弱参照をサポートする際に必要になります。
なので、オブジェクトのメモリサイズ最適化のために __slots__
をつかって
定義する際に、弱参照をサポートさせる場合は __weakref__
を含めておく必要があります。
class B: __slots__ = ('val') def __init__(self, val): self.val = val b = B() wref = weakref.ref(b)
とすると、以下のようになります。
TypeError: cannot create weak reference to 'B' object
__slots__
に含めてみます。
class C: __slots__ = ('val', '__weakref__') def __init__(self, val): self.val = val c = C(100) wref = weakref.ref(c)
今度はエラーなく処理できました。
サンプル
# coding: utf-8 """ weakref モジュールについてのサンプルです。 弱参照がオブジェクトの __weakref__ に設定されることを確認するサンプルです。 """ import weakref from trypython.common.commoncls import SampleBase from trypython.common.commonfunc import pr # noinspection PyUnusedLocal,SpellCheckingInspection,PyUnresolvedReferences class Sample(SampleBase): def exec(self): # ------------------------------------------------ # 弱参照は、オブジェクトの # __weakref__ # に設定される。 # # ただし、この属性が存在するのは # ユーザ定義クラス # の場合のみ。 # ------------------------------------------------ set01 = {1, 2} wref = weakref.ref(set01) pr('__weakref__ exists?', hasattr(set01, '__weakref__')) a = A() wref = weakref.ref(a) pr('__weakref__ exists?', hasattr(a, '__weakref__')) pr('a.__weakref__ is wref', a.__weakref__ is wref) # ------------------------------------------------ # ユーザ定義クラスで弱参照をサポートするためには # __weakref__ 属性が必要となる。__slots__ 属性を # つかって、オブジェクトのメモリサイズを最適化している # 場合、この属性を含めていないと弱参照が作れない。 # ------------------------------------------------ b = NotContainsWeakrefAttr(100) try: bref = weakref.ref(b) except TypeError as e: pr('NotContainsWeakrefAttr', e) c = ContainsWeakrefAttr(100) cref = weakref.ref(c) print(cref) class A: pass class NotContainsWeakrefAttr: __slots__ = ('val',) def __init__(self, val): self.val = val class ContainsWeakrefAttr: __slots__ = ('val', '__weakref__',) def __init__(self, val): self.val = val def go(): obj = Sample() obj.exec() if __name__ == '__main__': go()
出力結果は以下の通り。
__weakref__ exists?=False __weakref__ exists?=True a.__weakref__ is wref=True NotContainsWeakrefAttr=TypeError("cannot create weak reference to 'NotContainsWeakrefAttr' object",) <weakref at 0x00000000056C11D8; to 'ContainsWeakrefAttr' at 0x00000000056C04A8>
参考情報
3. データモデル — Python 3.6.3 ドキュメント

Fluent Python ―Pythonicな思考とコーディング手法
- 作者: Luciano Ramalho,豊沢聡,桑井博之,梶原玲子
- 出版社/メーカー: オライリージャパン
- 発売日: 2017/10/07
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ
サンプルコードは、以下の場所で公開しています。
- いろいろ備忘録日記サンプルソース置き場