2013-04-06 2 views
2

Допустим, вы делаете следующее:автореферентное списков в Python

a=[1] 
a[0]=a 

вы в конечном итоге с равным [[...]]. Что тут происходит? Как это неявно определяемая бесконечная цепочка a ссылается на a заканчивается на [[...]]?

+3

Как это неявное? Вы точно знаете, что вы делаете – jamylak

+2

'[...]' как Python представляет собой саморекламу в виде строки. См. Http://stackoverflow.com/questions/3728667/uses-of-self-referencing-lists – Stecman

ответ

5

Вы не видели ничего:

>>> a = [] 
>>> a[:] = [a] * 4 
>>> a 
[[...], [...], [...], [...]] 

Если вы заинтересованы в том, как это работает в CPython, см list_repr in listobject.c и аналогичные функции. В принципе, любая функция, которая потенциально печатает самореферентный объект, вызывает Py_ReprEnter на объекте перед его печатью и Py_ReprLeave, когда это будет сделано. (См. object.c for the definitions of these functions.) Первый проверяет, найден ли объект в потоковом стеке объектов, которые в настоящее время печатаются (а если нет, толкает его); последний выталкивает объект из стека. Так что, если Python печатает список и обнаруживает, что список находится в стеке, это должно означать, что это самоссылающегося список, и список должен быть сокращен, чтобы избежать бесконечного цикла:

i = Py_ReprEnter((PyObject*)v); 
if (i != 0) { 
    return i > 0 ? PyString_FromString("[...]") : NULL; 
} 

// ... 

Py_ReprLeave((PyObject *)v); 
return result; 
3

В списке содержится ссылка на себя. [[...]] - это то, как это отображается при печати списка.

Реализация идет не по пути, чтобы гарантировать, что это не закончится бесконечной рекурсией. Это делается путем отображения ссылок на объекты, которые уже печатаются как [...].

Это делает работу с косвенными автомодельными ссылками тоже:

>>> a = [] 
>>> b = [a] 
>>> a.append(b) 
>>> a 
[[[...]]] 
>>> b 
[[[...]]] 

Если вы действительно любопытно, вы можете изучать исходный код CPython в. В Python 2.7.3 соответствующий код находится в Objects/listobject.c.

+1

Просто хочу выделить что-то для OP, это не бесконечная рекурсия, потому что это всего лишь ** ссылка **, она на самом деле не пытается для передачи себя по значению – jamylak

+1

@jamylak: Правильно. Я имел в виду, что метод, который попытается вслепую пройти «a», закончится бесконечной рекурсией. – NPE

+0

О, я, наверное, должен был оставить этот комментарий по этому вопросу, я не ссылался на ваш ответ – jamylak

2

Мы a == [a] здесь, так что в теории a должны быть напечатаны в виде списка, содержащего один элемент, который является a --- то есть сам список, содержащий один элемент, который сам по себе является списком, содержащим один элемент, и так далее. Или в печати: бесконечное число [, за которым следует бесконечное число ]. Тот факт, что мы получаем вместо этого [[...]], - это просто Python, пытающийся быть полезным и не на самом деле печатать бесконечное число [.

Смежные вопросы