Notieren Sie sich das Ergebnis von Versuch und Irrtum und fragen Sie sich, wie eine entpackte Substitution realisiert wird.
>>> class MyTuple:
... def __getitem__(self, key):
... print(key)
... if key < 3:
... return str(key)
... else:
... raise IndexError
...
Es scheint, dass die Methode getitem () für die entpackte Zuweisung verwendet wird [^ 1]. Die Indexnummer wird als Schlüssel übergeben.
[^ 1]: Ich habe nach einem Dokument gesucht, aber es ist nicht sofort herausgekommen, also habe ich experimentiert und es nachgeschlagen.
getitem () wird nicht aufgerufen.
>>> x = MyTuple()
>>> x
<__main__.MyTuple object at 0x10a6bd850>
__Getitem__ ()
wird für die Anzahl der Elemente auf der linken Seite + 1 Mal aufgerufen.
Wenn "IndexError" in keinem der Aufrufe auftritt, wird angenommen, dass sich auf der rechten Seite viele Elemente befinden und "ValueError" auftritt.
>>> x, y = MyTuple()
0
1
2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)
__Getitem__ ()
wird für die Anzahl der Elemente auf der linken Seite + 1 Mal aufgerufen.
Wenn beim letzten Aufruf "IndexError" auftritt, wird davon ausgegangen, dass das linke und das rechte Element übereinstimmen und die Zuweisung erfolgreich ist.
>>> x, y, z = MyTuple()
0
1
2
3
>>> x, y, z
('0', '1', '2')
__Getitem__ ()
wird für die Anzahl der Elemente auf der linken Seite + 1 Mal aufgerufen.
Wenn "IndexError" in der Mitte des Aufrufs auftritt, wird davon ausgegangen, dass das Element auf der rechten Seite fehlt und die Zuweisung fehlschlägt.
>>> v, x, y, z = MyTuple()
0
1
2
3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 4, got 3)
*
Wenn sich auf der linken Seite ein Element mit "*" befindet, wird "getitem ()" aufgerufen, bis "IndexError" auftritt [^ 2]. Setzen Sie das Ergebnis auf nette Weise in die Variable auf der linken Seite ein.
[^ 2]: Gutes Gefühl ist PEP 3132 - Extended Iterable Unpacking.
>>> a, *b = MyTuple()
0
1
2
3
>>> a, b
('0', ['1', '2'])
Ein schönes Beispiel
>>> *a, b = MyTuple()
0
1
2
3
>>> a, b
(['0', '1'], '2')
Sie haben das Gefühl, dass Sie kein einziges Element haben müssen.
>>> *w, x, y, z = MyTuple()
0
1
2
3
>>> w, x, y, z
([], '0', '1', '2')
>>> w, *x, y, z = MyTuple()
0
1
2
3
>>> w, x, y, z
('0', [], '1', '2')
>>> w, x, *y, z = MyTuple()
0
1
2
3
>>> w, x, y, z
('0', '1', [], '2')
>>> w, x, y, *z = MyTuple()
0
1
2
3
>>> w, x, y, z
('0', '1', '2', [])
Aber wenn Sie keine zwei haben, können Sie nicht.
>>> *v, w, x, y, z = MyTuple()
0
1
2
3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected at least 4, got 3)
Sie können die Zuweisung auch entpacken, indem Sie "iter ()" anstelle von "getitem ()" implementieren.
>>> class MyTuple2():
... def __iter__(self):
... return iter([1, 2, 3])
...
Die Implementierung ist ziemlich kaputt, gibt jedoch einen Iterator für ein Array mit drei Elementen zurück. Es funktioniert richtig.
>>> x, y, z = MyTuple2()
>>> x, y, z
(1, 2, 3)
Es kann entweder "getitem ()" oder "iter ()" verwendet werden. Wenn es [iterierbar] ist (https://docs.python.org/ja/3/glossary.html#term-iterable), wird es entpackt. Es kann als ersetzbar umformuliert werden.
Beispiele für wiederholbare Objekte sind alle Sequenztypen (Liste, Str, Tupel usw.), einige Nicht-Sequenztypen wie Diktat- und Dateiobjekte oder die Methode
__iter__ ()
oder, die die Sequenzsemantik implementiert. Enthält eine Instanz einer Klasse mit der Methode __getitem__ ()
.
Recommended Posts