Что означает многоточие […] в списке?

196

Я играл на питоне. Я использовал следующий код в IDLE:

p  = [1, 2]
p[1:1] = [p]
print p

Выход был:

[1, [...], 2]

Что это […]? Интересно, что теперь я мог бы использовать это как список списка до бесконечности, т.е.

p[1][1][1]....

Я мог бы написать выше столько, сколько я хотел, и это все еще будет работать.

РЕДАКТИРОВАТЬ:

  • Как это представлено в памяти?
  • Каково его использование? Примеры некоторых случаев, когда это полезно, было бы полезно.
  • Любая ссылка на официальную документацию была бы действительно полезной.
Aseem Bansal
источник
Все еще ищите ответы на 1-й и 3-й элемент списка EDIT.
Aseem Bansal
7
Более простой пример будет p = [1]; p[0] = p.
Аршаджи
6
Я думаю, что это дубликат того, что […] (многоточие) в списке означает на Python? , хотя вопрос (и ответы) лучше в этом вопросе.
Мартин Тома
1
Dreampie умный `>>> p [1: 1] = [p] >>> p 3: [1, <Рекурсия по списку с id = 3074777548>, 2] >>>` предоставьте точную информацию
Рахул Гаутам
@RahulGautam Не понял этого p 3: [1, <Recursion on list with id=3074777548>, 2]. Что ты бежал?
Aseem Bansal

Ответы:

112

Это означает, что вы создали бесконечный список, вложенный внутрь себя, который нельзя распечатать. pсодержит, pкоторый содержит p... и так далее. [...]Нотация является способом , чтобы вы знали это, и сообщить , что он не может быть представлен! Посмотрите на ответ @ 6502, чтобы увидеть красивую картинку, показывающую, что происходит.

Теперь о трех новых пунктах после вашего редактирования:

  • Этот ответ, кажется, покрывает это
  • Ссылка Игнасио описывает некоторые возможные применения
  • Это больше тема проектирования структуры данных, чем языков программирования, поэтому вряд ли какая-либо ссылка будет найдена в официальной документации Python
Оскар Лопес
источник
Значит, это забирает бесконечную память? Я знаю, что это невозможно. Как это представлено и для чего оно используется?
Aseem Bansal
21
@Zel: элементы списка являются ссылками. Второй элемент - это ссылка на сам список.
Игнасио Васкес-Абрамс
2
Python идентифицировал его как бесконечный цикл ссылок, поэтому решил сократить его, на самом деле он не бесконечен. И нет, это не очень полезно, кроме мысленного эксперимента :)
Оскар Лопес
2
Есть ... несколько вариантов использования бесконечно рекурсивных структур. Но не много.
Игнасио Васкес-Абрамс
@ IgnacioVazquez-Abrams Некоторые примеры будут полезны.
Aseem Bansal
316

Это то, что ваш код создан

введите описание изображения здесь

Это список, где первый и последний элементы указывают на два числа (1 и 2), а средний элемент указывает на сам список.

В Common Lisp, когда печать круговых структур включена, такой объект будет напечатан как

#1=#(1 #1# 2)

это означает, что существует объект (помеченный 1 с #1=), который является вектором с тремя элементами, второй является самим объектом (обратная ссылка с #1#).

Вместо этого в Python вы просто получаете информацию о том, что структура круговая [...].

В этом конкретном случае описание не является двусмысленным (это обратное указание на список, но существует только один список, поэтому он должен быть тем). В других случаях может быть, однако, неоднозначным ... например, в

[1, [2, [...], 3]]

обратная ссылка может указывать либо на внешний, либо на внутренний список. Эти две разные структуры, напечатанные одинаково, могут быть созданы с

x = [1, [2, 3]]
x[1][1:1] = [x[1]]

y = [1, [2, 3]]
y[1][1:1] = [y]

print(x)
print(y)

и они будут в памяти как

введите описание изображения здесь

6502
источник
Вы можете найти содержимое [1, [2, [...], 3]]как это: x[1] = [2, [...], 3]и y[1] = [2, 1, [...]], 3]. Это означает, что x состоит из 1 и затем повторяющихся 2s, тогда как y состоит из чередующихся 1s и 2s.
pascalhein
2
@csharpler: конечно, вы можете различить их, анализируя содержимое, однако они печатаются с одинаковым представлением. В формате Common Lisp вместо этого они будут #(1 #1=#(2 #1# 3))для xи #1=#(1 #(2 #1# 3))для y.
6502
5
@BurhanKhalid: inkscape для первого и gimp для второго (потому что я выбросил svg)
6502
1
@csharpler: вы не можете создать «бесконечный список» в Python, потому что списки действительно являются массивами с изменяемым размером, а не связанными списками. Вместо этого можно создать «бесконечный список» в Common Lisp с помощью #1=(1 . #1#).
6502
1
+ если вы хотите нарисовать диаграмму acsii следующим образом: Asiiflow
Grijesh Chauhan
23

На вопрос «Что это такое», приведу конкретный пример.

Сокращение графика - это стратегия оценки, которая иногда используется для интерпретации компьютерного языка. Это общая стратегия для ленивых вычислений, особенно функциональных языков.

Отправной точкой является построение графика, представляющего последовательность «шагов», которые предпримет программа. В зависимости от управляющих структур, используемых в этой программе, это может привести к циклическому графу (поскольку программа содержит некий «вечный» цикл - или использовать рекурсию, «глубина» которой будет известна во время оценки , но не на графике). время создания ) ...

Чтобы представить такой граф, вам нужны бесконечные «структуры данных» (иногда называемые рекурсивными структурами данных), подобные той, которую вы заметили. Обычно немного сложнее, хотя.

Если вы заинтересованы в этой теме, вот (среди многих других) лекция на эту тему:
http://undergraduate.csse.uwa.edu.au/units/CITS3211/lectureNotes/14.pdf

Сильвен Леру
источник
7

Мы делаем это все время в объектно-ориентированном программировании. Если любые два объекта ссылаются друг на друга, прямо или косвенно, они оба являются бесконечно рекурсивными структурами (или обе являются частью одной бесконечно рекурсивной структуры, в зависимости от того, как вы на нее смотрите). Вот почему вы не видите этого в чем-то столь же примитивном, как список - потому что мы обычно лучше описываем концепцию как взаимосвязанные «объекты», чем «бесконечный список».

Вы также можете получить ...бесконечно рекурсивный словарь. Допустим, вам нужен словарь углов треугольника, где каждое значение является словарем других углов, соединенных с этим углом. Вы можете настроить его так:

a = {}
b = {}
c = {}
triangle = {"a": a, "b": b, "c": c}
a["b"] = b
a["c"] = c
b["a"] = a
b["c"] = c
c["a"] = a
c["b"] = b

Теперь , если вы печатаете triangle(или aили bили cна то пошло), вы увидите , что он полон , {...}потому что любые два угла имеют в виду обратно друг к другу.

nmclean
источник
Пример более a = {}; a['a'] = a; print a['a']['a']['a']
простого
Для меня вместо «...» это показывает «<рекурсия по dict с id = ___>»
Соломон Уко
@SolomonUcko Вы, вероятно, используете IPython, который автоматически использует pprint для печати. Если вы напечатаете, %pprintчтобы отключить симпатичную печать, он покажет ....
nmclean
4

Как я понял, это пример с фиксированной точкой

p  = [1, 2]
p[1:1] = [p]
f = lambda x:x[1]
f(p)==p
f(f(p))==p
Hanfei Sun
источник
Я не смог этого понять. Пытался выполнить эти команды, но есть ошибки.
Aseem Bansal
@Zel: Ну, перед этим нужно добавить код OP, чтобы объявить p.
Inkane
1
@Zel: Ну, я не уверен, насколько он мне полезен, но Firegun говорит, что p (и, следовательно, p [1], представленное как [...]) - это точка фиксации функции f. ИМХО, это возможный ответ на вопрос "Что такое [...]?" в таком случае.
Inkane
1
У меня возникла та же ошибка, потому что я попробовал этот пример после того, как попробовал более простой p = [1]; p[0] = pпример, который должен f = lambda x:x[0]работать. Это пример точки исправления, но я пока не смог понять, насколько полезно это знать. Реальное значение точки фиксации заключается в ее достижении из некоторой другой точки рекурсивным или итеративным образом. Пример, который показывает, как использовать структуру списка исходного вопроса для создания комбинатора Y, будет полезен, если это возможно.
Дансалмо
1
q = lambda: qделает бесконечно вызываемую лямбду
whackamadoodle3000
-2

Название этого специального объекта - Ellipsis. Я предполагаю, что он реализован как одноэлементный объект в Python intepreter / VM - что-то вроде None - своего рода часовой. Как вы уже видели, это способ для Python представить ссылку на список внутри себя.

Джим Деннис
источник
Как ни странно, нет никакого способа напрямую создать экземпляр объекта Ellipsis. Например, имя не раскрывается через интерфейс Builtins. Таким образом, вы можете увидеть ссылки на термин в определенных ошибках (повышенные исключения), например, если вы попытаетесь извлечь элемент, используя многоточие в качестве индекса. Но вы можете просто сказать: el = Ellipsis () или что-нибудь подобное (что я нашел).
Джим Деннис,
9
Это на самом деле не имеет ничего общего с объектом Ellipsis. Это просто буквенная строка «[...]», которая печатается при обнаружении цикла во время печати списка. См. Код: hg.python.org/cpython/file/84d6c1c0665e/Objects/…
Джереми Шарп