Make a note of the result of trial and error, wondering how the unpacked substitution was realized.
__getitem__ ()
>>> class MyTuple:
... def __getitem__(self, key):
... print(key)
... if key < 3:
... return str(key)
... else:
... raise IndexError
...
It seems that the __getitem__ ()
method is used for unpacked assignment [^ 1].
The index number is passed as the key.
[^ 1]: I searched for the document, but it didn't come out at once, so I experimented and looked it up.
__getitem__ ()
is not called.
>>> x = MyTuple()
>>> x
<__main__.MyTuple object at 0x10a6bd850>
__Getitem__ ()
is called for the number of elements on the left side + 1 time.
If ʻIndexError does not occur in any of the calls, it is assumed that there are many elements on the right side, and
ValueError` occurs.
>>> 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__ ()
is called for the number of elements on the left side + 1 time.
If the last call raises ʻIndexError`, it assumes that the left and right elements match and the assignment succeeds.
>>> x, y, z = MyTuple()
0
1
2
3
>>> x, y, z
('0', '1', '2')
__Getitem__ ()
is called for the number of elements on the left side + 1 time.
If ʻIndexError` occurs in the middle of the call, it is considered that the element on the right side is missing and the assignment fails.
>>> 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)
*
If there is an element with *
on the left side, __getitem__ ()
will be called until ʻIndexError` occurs [^ 2].
Substitute the result into the variable on the left side nicely.
[^ 2]: Good feeling is PEP 3132 --Extended Iterable Unpacking.
>>> a, *b = MyTuple()
0
1
2
3
>>> a, b
('0', ['1', '2'])
A nice example
>>> *a, b = MyTuple()
0
1
2
3
>>> a, b
(['0', '1'], '2')
It makes you feel like you don't have to have one element.
>>> *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', [])
But if you don't have two, you can't.
>>> *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)
__iter__ ()
You can also unpack assign by implementing __iter__ ()
instead of __getitem__ ()
.
>>> class MyTuple2():
... def __iter__(self):
... return iter([1, 2, 3])
...
The implementation is pretty broken, but it returns an iterator for an array with three elements. It works properly.
>>> x, y, z = MyTuple2()
>>> x, y, z
(1, 2, 3)
Either __getitem__ ()
or __iter__ ()
can be used, which means that iterable is unpacked. It can be rephrased as substitutable.
Examples of repeatable objects include all sequence types (list, str, tuple, etc.), some non-sequence types, such as dict and file objects, or the
__iter__ ()
method orwhich implements Sequence semantics. Contains an instance of any class that has the __getitem__ ()
method.
Recommended Posts