次のことをするとします。
a = [1]
a[0] = a
最終的にはa
as equal to になり[[...]]
ます。何が起きてる?a
この暗黙的に定義された の無限チェーンの 参照は、どのようにa
終了するの[[...]]
でしょうか?
次のことをするとします。
a = [1]
a[0] = a
最終的にはa
as equal to になり[[...]]
ます。何が起きてる?a
この暗黙的に定義された の無限チェーンの 参照は、どのようにa
終了するの[[...]]
でしょうか?
あなたは何も見ていない:
>>> a = []
>>> a[:] = [a] * 4
>>> a
[[...], [...], [...], [...]]
これが CPython でどのように機能するかに興味がある場合は、list_repr
inlistobject.c
および同様の関数を参照してください。基本的に、自己参照オブジェクトを出力する可能性のある関数は、出力Py_ReprEnter
前Py_ReprLeave
と完了時にオブジェクトを呼び出します。(object.c
これらの関数の定義については、 を参照してください。) 前者は、現在印刷中のオブジェクトのスレッド ローカル スタック内にオブジェクトが見つかるかどうかを確認します (見つからない場合はプッシュします)。後者はオブジェクトをスタックからポップします。したがって、Python がリストを出力していて、そのリストがスタック上にあることを発見した場合、それはこれが自己参照リストであることを意味し、無限ループを避けるためにリストを省略しなければなりません:
i = Py_ReprEnter((PyObject*)v);
if (i != 0) {
return i > 0 ? PyString_FromString("[...]") : NULL;
}
// ...
Py_ReprLeave((PyObject *)v);
return result;
リストには、それ自体への参照が含まれています。これ[[...]]
は、リストを印刷するときにレンダリングされる方法です。
実装は、無限再帰にならないように最善を尽くします。として既に印刷されているオブジェクトへの参照をレンダリングすることでこれを行います[...]
。
これにより、間接的な自己参照でも機能します。
>>> a = []
>>> b = [a]
>>> a.append(b)
>>> a
[[[...]]]
>>> b
[[[...]]]
本当に興味がある場合は、CPython のソース コードを調べることができます。Python 2.7.3 では、関連するコードは にありObjects/listobject.c
ます。
つまり、それ自体が 1 つの要素を含むリストであり、それ自体が 1 つの要素を含むリストであるということですa == [a]
。または印刷物: の無限数 の後に無限の が続きます。代わりに得られるのは、Python が役に立ちようとしているだけであり、実際には無限の.a
a
[
]
[[...]]
[