2014-02-15 9 views
11

So stieß ich in Python auf etwas sehr Seltsames. Ich habe versucht, einen Verweis auf die Liste hinzuzufügen. Der Code könnte dazu beitragen, das, was ich sage, besser zu demonstrieren, als ich ausdrücken kann. Ich benutze den IDLE-Editor (interaktiver Modus).Rekursiver Verweis auf eine Liste in sich selbst

>>>l=[1,2,3] 
>>>l.append(l) 
>>>print(l) 
[1,2,3,[...]] 
>>>del l[:-1] 
>>>print(l) 
[[...]] 

Bis jetzt ist die Ausgabe wie erwartet. Aber wenn ich das tue.

y=l[:] 
print(y) 

Mir scheint es, dass die Ausgabe

[[...]] 

sein sollte, aber es ist

[[[...]]] 

Anscheinend stattdessen eine Kopie der Liste zu erstellen, legt es einen Verweis auf die Liste in y.

y [0] ist l gibt True zurück. Ich kann keine gute Erklärung dafür finden. Irgendwelche Ideen?

Antwort

8

Der Unterschied besteht nur in der Art, wie die Liste angezeigt wird. I.e. Der Wert von y ist genau das, was Sie erwarten würden.

Der Unterschied in der Art und Weise werden die Listen ergibt sich aus der Tatsache angezeigt, dass im Gegensatz l, y kein sich selbst verweisende Liste ist:

l[0] is l 
=> True 
y[0] is y 
=> False 

y ist nicht selbst Referenzierung, da y nicht referenziert y. Es verweist auf l, das sich selbst referenziert.

Daher erkennt die Logik, die die Liste in eine Zeichenfolge übersetzt die potenzielle unendliche Rekursion eine Ebene tiefer bei der Arbeit an y, als auf l.

3

Dies ist perfekt zu erwarten. Wenn Python rekursive Listen druckt, prüft es, ob die Liste, die es druckt, noch nicht gefunden wurde und ob es Ausdrucke [...] hat. Ein wichtiger Punkt zu verstehen ist, dass es nicht für Gleichheit (wie in ==), sondern für Identität (wie in is) testen. Daher

  • beim Drucken l = [l]. Sie haben l[0] is l gibt True zurück und deshalb druckt es [[...]].

  • jetzt macht y = l[:] eine Kopie l und damit y is l kehrt False. Also hier ist was passiert. Es beginnt zu drucken y so druckt es [??? ] wobei ??? durch den Druck y[0] ersetzt wird. Jetzt ist y[0]l und ist nicht y. So druckt [[???]] mit ??? ersetzt durch y[0][0]. Jetzt y[0][0] ist l, die bereits angetroffen wurde. So druckt es [...] für es geben schließlich [[[...]]].

+0

Könnten Sie näher ausführen? Du hast mich verloren bei ** "Es fängt an zu drucken y: [???] ..... ** – Guy

+0

Auch was, wenn ich eigentlich eine Kopie der Liste wollte? Ich weiß, dass ich in diesem Fall einfach dasselbe mit y machen kann Aber um der Diskussion willen gibt es einen Weg, wie ich es tun kann? – Guy

+0

@Sabyasachi: Es ist klarer so? – hivert

1

Slicing erzeugt eine Liste von Elementen. Es gibt nur einen Gegenstand - Liste "l". Also haben wir eine neue Liste von einem Element - Liste "l".

2

Sie müssen eine vollständige Kopie der Objekte haben. Sie müssen copy.deepcopy verwenden und Sie würden die erwarteten Ergebnisse sehen.

>>> from copy import deepcopy 
>>> l=[1,2,3] 
>>> l.append(l) 
>>> print(l) 
[1, 2, 3, [...]] 
>>> del l[:-1] 
>>> print(l) 
[[...]] 
>>> y=deepcopy(l) 
>>> print(y) 
[[...]] 
>>> y[0] is l 
False 
>>> 

Wenn Sie die Slice-Notation verwenden, um die Liste zu kopieren, werden die inneren Referenzen beibehalten, die das Verhalten verursachen, die zu beachten.

Verwandte Themen