From the docs relative to async for
syntax in Python 3.5, I gathered that it was introduced to iterate over an awaitable iterator.
There is something I don’t get in the semantic equivalent that follow the description though:
JavaScript
x
13
13
1
iter = (ITER)
2
iter = type(iter).__aiter__(iter)
3
running = True
4
while running:
5
try:
6
TARGET = await type(iter).__anext__(iter)
7
except StopAsyncIteration:
8
running = False
9
else:
10
BLOCK
11
else:
12
BLOCK2
13
What is the line iter = type(iter).__aiter__(iter)
doing? Why is it necessary?
Advertisement
Answer
Magic methods in python, e.g. __add__
, are always looked up on the class. For example, len(foo)
will actually call resolve to type(foo).__len__(foo)
. This means it will never use a foo.__len__
if __len__
is defined on foo
.
Since __aiter__
is a magic method, it is thus always looked up as type(foo).__aiter__(foo)
.
Example for lookup:
JavaScript
1
11
11
1
class Thingy(object):
2
def __len__(self):
3
return 10
4
5
lengthy_thingy = Thingy()
6
lengthy_thingy.__len__ = lambda self: 20
7
8
print(len(lengthy_thingy)) # gives `10`
9
print(lengthy_thingy.__len__(lengthy_thingy)) # gives `20` instead
10
print(type(lengthy_thingy).__len__(lengthy_thingy)) # gives `10` as for using `len`
11