Que signifient les points de suspension […] dans une liste?

196

Je jouais en python. J'ai utilisé le code suivant dans IDLE:

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

Le résultat était:

[1, [...], 2]

Qu'est-ce que c'est […]? Fait intéressant, je pourrais maintenant l'utiliser comme une liste de liste de liste jusqu'à l'infini, c'est-à-dire

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

Je pourrais écrire ce qui précède aussi longtemps que je le souhaite et cela fonctionnerait toujours.

ÉDITER:

  • Comment est-il représenté en mémoire?
  • Quel est son utilisation? Des exemples de certains cas où il est utile seraient utiles.
  • Tout lien vers la documentation officielle serait vraiment utile.
Aseem Bansal
la source
Toujours à la recherche de réponses aux 1er et 3e éléments de la liste EDIT.
Aseem Bansal
7
Un exemple plus simple serait p = [1]; p[0] = p.
arshajii
6
Je pense que c'est un doublon de Que signifie […] (points de suspension) dans une liste en Python? , bien que la question (et les réponses) soient meilleures dans cette question.
Martin Thoma
1
Dreampie est intelligent `>>> p [1: 1] = [p] >>> p 3: [1, <Récursivité sur la liste avec id = 3074777548>, 2] >>>` fournit les détails exacts
Rahul Gautam
@RahulGautam N'a pas compris cela p 3: [1, <Recursion on list with id=3074777548>, 2]. Qu'avez-vous couru?
Aseem Bansal

Réponses:

112

Cela signifie que vous avez créé une liste infinie imbriquée en elle-même, qui ne peut pas être imprimée. pcontient pqui contient p... et ainsi de suite. La [...]notation est un moyen de vous le faire savoir et d'informer qu'elle ne peut pas être représentée! Jetez un œil à la réponse de @ 6502 pour voir une belle image montrant ce qui se passe.

Maintenant, concernant les trois nouveaux éléments après votre modification:

  • Cette réponse semble la couvrir
  • Le lien d'Ignacio décrit quelques utilisations possibles
  • Il s'agit plus d'un sujet de conception de structure de données que de langages de programmation, il est donc peu probable qu'une référence soit trouvée dans la documentation officielle de Python
Óscar López
la source
Alors, cela prend-il une mémoire infinie? Je sais que cela ne peut pas être possible. Comment est-il représenté et à quoi sert-il?
Aseem Bansal
21
@Zel: Les éléments de liste sont des références. Le deuxième élément est une référence à la liste elle-même.
Ignacio Vazquez-Abrams
2
Python l'a identifié comme une boucle infinie de références, alors il a décidé de le raccourcir, ce n'est pas vraiment infini. Et non, ce n'est pas vraiment utile à part une expérience de pensée :)
Óscar López
2
Il y a ... quelques utilisations pour des structures infiniment récursives. Mais pas beaucoup.
Ignacio Vazquez-Abrams
@ IgnacioVazquez-Abrams Quelques exemples seraient utiles.
Aseem Bansal
316

C'est ce que votre code a créé

entrez la description de l'image ici

C'est une liste où le premier et le dernier éléments pointent vers deux nombres (1 et 2) et où l'élément du milieu pointe vers la liste elle-même.

En Common Lisp, lorsque l'impression de structures circulaires est activée, un tel objet sera imprimé sous la forme

#1=#(1 #1# 2)

ce qui signifie qu'il existe un objet (étiqueté 1 avec #1=) qui est un vecteur à trois éléments, le second étant l'objet lui-même (référencé avec #1#).

En Python, vous obtenez simplement les informations avec lesquelles la structure est circulaire [...].

Dans ce cas précis, la description n'est pas ambiguë (elle pointe vers une liste en arrière mais il n'y a qu'une seule liste donc elle doit être celle-là). Dans d'autres cas, cela peut être ambigu ... par exemple dans

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

la référence arrière pourrait pointer vers la liste externe ou vers la liste interne. Ces deux structures différentes imprimées de la même manière peuvent être créées avec

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

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

print(x)
print(y)

et ils seraient en mémoire

entrez la description de l'image ici

6502
la source
Vous pouvez trouver le contenu de ce qui [1, [2, [...], 3]]suit: x[1] = [2, [...], 3]et y[1] = [2, 1, [...]], 3]. Cela signifie que x consiste en un 1 puis en répétant 2, tandis que y consiste à alterner 1 et 2.
pascalhein
2
@csharpler: bien sûr, vous pouvez distinguer les deux en analysant le contenu, mais ils sont imprimés avec la même représentation. Au format Common Lisp, ils seraient plutôt #(1 #1=#(2 #1# 3))pour xet #1=#(1 #(2 #1# 3))pour y.
6502
5
@BurhanKhalid: inkscape pour le premier et gimp pour le second (parce que j'ai jeté le svg)
6502
1
@csharpler: vous ne pouvez pas créer une "liste infinie" en Python car les listes sont en effet des tableaux redimensionnables, pas des listes liées. Une "liste infinie" en Common Lisp pourrait à la place être créée avec #1=(1 . #1#).
6502
1
+ si vous voulez dessiner un diagramme acsii comme celui-ci, essayez: Asiiflow
Grijesh Chauhan
23

A la question "Quelle est son utilisation", voici un exemple concret.

La réduction des graphes est une stratégie d'évaluation parfois utilisée pour interpréter un langage informatique. Il s'agit d'une stratégie courante pour l'évaluation paresseuse, notamment des langages fonctionnels.

Le point de départ est de construire un graphique représentant la séquence des "étapes" du programme. Selon les structures de contrôle utilisées dans ce programme, cela peut conduire à un graphique cyclique (parce que le programme contient une sorte de boucle "pour toujours" - ou utiliser une récursion dont la "profondeur" sera connue au moment de l' évaluation , mais pas au niveau du graphique- temps de création ) ...

Afin de représenter un tel graphique, vous avez besoin d' infinies «structures de données» (parfois appelées structures de données récursives ), comme celle que vous avez remarquée. Habituellement, un peu plus complexe cependant.

Si vous êtes intéressé par ce sujet, voici (parmi bien d'autres) une conférence sur ce sujet:
http://undergraduate.csse.uwa.edu.au/units/CITS3211/lectureNotes/14.pdf

Sylvain Leroux
la source
7

Nous le faisons tout le temps en programmation orientée objet. Si deux objets se réfèrent l'un à l'autre, directement ou indirectement, ils sont tous les deux des structures infiniment récursives (ou les deux font partie de la même structure infiniment récursive, selon la façon dont vous le regardez). C'est pourquoi vous ne voyez pas cela autant dans quelque chose d'aussi primitif qu'une liste - car il vaut généralement mieux décrire le concept comme des «objets» interconnectés que comme une «liste infinie».

Vous pouvez également obtenir ...avec un dictionnaire infiniment récursif. Disons que vous voulez un dictionnaire des coins d'un triangle, où chaque valeur est un dictionnaire des autres coins connectés à ce coin. Vous pouvez le configurer comme ceci:

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

Maintenant, si vous imprimez triangle(ou aou bou cd'ailleurs), vous verrez qu'il est plein {...}car deux coins se réfèrent l'un à l'autre.

nmclean
la source
Exemple de dictionnaire plus simple:a = {}; a['a'] = a; print a['a']['a']['a']
user650654
Pour moi, au lieu de "..." cela montre "<Récursion sur dict avec id = ___>"
Solomon Ucko
@SolomonUcko Vous utilisez probablement IPython qui utilise automatiquement pprint pour imprimer des choses. Si vous tapez %pprintpour désactiver la jolie impression, cela s'affichera ....
nmclean
4

Si je comprends bien, ceci est un exemple de point fixe

p  = [1, 2]
p[1:1] = [p]
f = lambda x:x[1]
f(p)==p
f(f(p))==p
Hanfei Sun
la source
Je n'ai pas pu comprendre cela. J'ai essayé d'exécuter ces commandes mais il y a des erreurs.
Aseem Bansal
@Zel: Eh bien, vous devez ajouter du code OP avant qu'il ne soit déclaré.
Inkane
1
@Zel: Eh bien, je ne sais pas à quel point c'est utile moi-même, mais Firegun dit que p (et donc p [1], représenté comme [...]) est un point fixe de la fonction f. À mon humble avis, ceci est une réponse possible à la question "Qu'est-ce que [...]?" dans ce cas.
Inkane
1
J'ai eu le même problème d'erreur parce que j'avais essayé cet exemple après avoir essayé l' p = [1]; p[0] = pexemple plus simple qui doit f = lambda x:x[0]fonctionner. C'est un exemple de point fixe, mais je n'ai pas encore pu voir à quel point le savoir est utile. La valeur réelle du point fixe est d'y arriver à partir d'un autre point de manière récursive ou itérative. Un exemple qui montre comment utiliser la structure de liste de la question d'origine pour créer le combinateur Y serait utile s'il est possible.
dansalmo
1
q = lambda: qfait un lambda infiniment appelable
whackamadoodle3000
-2

Le nom de cet objet spécial est les points de suspension. Je suppose qu'il est implémenté en tant qu'objet singleton dans l'interprète / VM Python - quelque chose comme None - une sorte de sentinelle. Comme vous l'avez vu, c'est un moyen pour Python de représenter la référence d'une liste en lui-même.

Jim Dennis
la source
Curieusement, il ne semble pas y avoir de moyen d'instancier directement un objet Ellipsis. Le nom n'est pas exposé via l'interface Builtins par exemple. Ainsi, vous pouvez voir des références au terme dans certaines erreurs (exceptions déclenchées), par exemple si vous essayez d'extraire un élément en utilisant des points de suspension comme index. Mais vous pouvez simplement dire: el = Ellipsis () ni quelque chose comme ça (que j'ai trouvé).
Jim Dennis
9
Cela n'a en fait rien à voir avec l'objet Ellipsis. C'est juste la chaîne littérale "[...]", qui est imprimée lorsqu'un cycle est détecté lors de l'impression d'une liste. Voir le code: hg.python.org/cpython/file/84d6c1c0665e/Objects/…
Jeremy Sharpe