自分自身を参照するNodeのlistでの実装(Python)

2024/09/23に公開

こんにちは、沙代です。
PythonでNodeをlistで実装するときに、自分自身を参照させたい時ってありますよね。
ちょっと試してみたので、まとめてみました。

環境
MacOS: macOS Montery 12.6.2 (Apple M1 Pro)
iTerm2: 3.5.4
Python: 3.7.0

TL;DR

>>> a = [None, 'generation0']  # 単にa = [] でも可
>>> a[:] = [a, 'generation0']  # 単にa[0] = a でも可
>>> a
[[...], 'generation0']
>>> a[0]
[[...], 'generation0']
>>> a is a[0]
True

詳しく

Nodeを準備します

[親Node, 世代名]でNodeをlistで表現したい。
第0世代の親は自分自身としたい。

>>> a = [None, 'generation0']
>>> b = [a, 'generation1']

問題点

>>> a = [a, 'generation0']
>>> a
[[None, 'generation0'], 'generation0']
>>> a[0]
[None, 'generation0']

aa[0]は別物になっています。

解決策

>>> a[:] = [a, 'generation0']
>>> a
[[...], 'generation0']
>>> a[0]
[[...], 'generation0']
>>> a is a[0]
True

a[:]を使うことで、自分自身に参照させることができました!
(a[0] = aでも大丈夫です!)

その他

他の例として、functools.lru_cache実装では、

Lib/functools.py
    root = []                # root of the circular doubly linked list
    root[:] = [root, root, None, None]     # initialize by pointing to self

として書かれており、この場合は[:]スライス代入の方が見やすいかもしれません。

最後に

ちょっとサッと実装したいときに便利ですね。コードを共有するとびっくりされてしまうかもしれませんが。汗

参考ページ

Discussion