Categories: Python

【Python】クラスの全てのインスタンスをリストで扱う

この記事では、特定のクラスの全インスタンスをリストから扱えるようにする方法を解説します。

クラスのインスタンスをリストで扱えるようにするには 弱参照 を使うと簡単です。弱参照とは、元のオブジェクトが削除された場合に消える参照のこと を言います。

それでは、クラスのインスタンスをリストで扱う方法を見ていきましょう!

クラスのインスタンスをリストで扱う

クラスのインスタンスをリストとして扱うには、インスタンスへの弱参照を持つリストをクラス変数として保持させ、コンストラクタで弱参照をリストに追加することで実現できます。

import weakref

class C:
    # クラスの参照を保存するリスト
    references = []

    def __init__(self, val) -> None:
        self.val = val

        # リストにインスタンスの弱参照を追加
        C.references.append(weakref.ref(self))

実際に上記クラスをインスタンス化して呼び出してみます。

# インスタンス化
c1 = C(1)
c2 = C(2)
c3 = C(3)

# 呼び出し
for ref in C.references:
    # 参照なので () が必要
    r = ref()
    # クラス名と変数の呼び出し
    print(r.__class__, r.val)

実行結果

<class '__main__.C'> 1
<class '__main__.C'> 2
<class '__main__.C'> 3

これでクラスの全インスタンスの弱参照をリストで扱うことができます。

参照を削除する

インスタンスが削除された場合、弱参照はNoneTypeとして扱われる。

import weakref

class C:
    # クラスの参照を保存するリスト
    references = []

    def __init__(self, val) -> None:
        self.val = val

        # リストにインスタンスの弱参照を追加
        C.references.append(weakref.ref(self))

# インスタンス化
c1 = C(1)
c2 = C(2)
c3 = C(3)

# インスタンスの削除
del c2

# 呼び出し
for ref in C.references:
    r = ref()
    print(r.__class__, r.val)

実行結果

<class '__main__.C'> 1
Traceback (most recent call last):
  File "main.py", line 22, in <module>
    print(r.__class__, r.val)
AttributeError: 'NoneType' object has no attribute 'val'

インスタンスが削除された時にリストから弱参照も削除したい場合は、弱参照を生成する時に以下のようなラムダ式をコールバックとして定義しておくと楽ちん。

weakref.ref(self, lambda ref: C.references.remove(ref))

これで削除されたインスタンスの弱参照は勝手にリストから削除されます。

import weakref

class C:
    # クラスの参照を保存するリスト
    references = []

    def __init__(self, val) -> None:
        self.val = val

        # リストにインスタンスの弱参照を追加
        C.references.append(weakref.ref(self, lambda ref: C.references.remove(ref)))

# インスタンス化
c1 = C(1)
c2 = C(2)
c3 = C(3)

# インスタンスの削除
del c2

# 呼び出し
for ref in C.references:
    r = ref()
    print(r.__class__, r.val)

実行結果

<class '__main__.C'> 1
<class '__main__.C'> 3

まとめ

この記事では、特定のクラスの全インスタンスをリストで扱う方法を解説しました。

もし、全クラスのインスタンスをまとめたい場合は、リストをグローバル変数として定義すれば可能ですが、組み込み型の弱参照は生成できないのでサブクラスを定義する必要があります。

それでは今回の内容はここまでです。ではまたどこかで〜( ・∀・)ノ

ゆうまる

独学でプログラミングを勉強しているおじさん。いろんな言語を勉強したが浅く広くなためあまり仕事につながらない。また忘れっぽいため自分のブログを備忘録としても使っている。産まれてこのかたずっとネコを飼ってる生粋のネコ派。最近お腹が出てきて筋トレに奮闘中!

Recent Posts

【Dart】コンストラクタのデフォルト引数について

Dartのコンストラクタのデフォルト引数…

2週間 ago

【Unity】有料アセットを無料で手に入れる方法

この記事では、Unityの有料アセットを…

4か月 ago

【Python】任意の秒数だけ処理を一時停止する方法【sleep()関数】

この記事では、Pythonで任意の秒数だ…

1年 ago

【Python】Wordの文書の新規作成と読み書き

この記事では、Pythonを使ってWor…

1年 ago

【Python】メタクラスって結局なんなの?

この記事では、Pythonのメタクラスに…

1年 ago