Обложка канала

Библиотека Python разработчика

20835 @BookPython

Библиотека Python разработчика. Книги по программированию на Python.

Библиотека Python разработчика

4 года назад
Открыть в
Both for and with can be asynchronous. async with uses __aenter__ and __aexit__ magic methods, async for uses __aiter__ and __anext__. All of them are async and you can await within them: import asyncio class Sleep: def __init__(self, t): self._t = t async def __aenter__(self): await asyncio.sleep(self._t / 2) async def __aexit__(self, *args): await asyncio.sleep(self._t / 2) async def main(): async with Sleep(2): print('*') loop = asyncio.get_event_loop() loop.run_until_complete(main()) When you implement __iter__ you often don't write an iterator with __next__ method, you just use yield that makes __iter__ a generator: class Bracketed: def __init__(self, data): self._data = data def __iter__(self): for x in self._data: yield '({})'.format(x) print(list(Bracketed([1, 2, 3]))) # ['(1)', '(2)', '(3)'] PEP 525 allows you do the same with __aiter__. Both yield and await in the function body make it asynchronous generator. While await is used to communicate with the loop, yield deals with for: import asyncio class Slow: def __init__(self, data, t=1): self._data = data self._t = t async def __aiter__(self): for x in self._data: await asyncio.sleep(self._t) yield x async def main(): async for x in Slow([1, 2, 3]): print(x) loop = asyncio.get_event_loop() loop.run_until_complete(main())