Напишите класс FilterQueue со следующими свойствами:
Это потомок asyncio.Queue
В экземпляре класса атрибут очередь.window содержит первый элемент очереди, или None, если очередь пуста
С помощью операции фильтр in очередь можно определить, присутствуют ли в очереди такие элементы, что выражение фильтр(элемент) истинно
Метод .later() синхронно переставляет первый элемент очереди в её конец, или вызывает исключение asyncio.QueueEmpty, если очередь пуста
Метод .get() содержит необязательный параметр фильтр. Вызов очередь.get(фильтр) работает так:
Если в очереди нет элементов, на которых фильтр(элемент) истинно, работает как обычный .get().
Если в очереди есть элементы, на которых фильтр(элемент) истинно, переставляет первый элемент очереди в её конец до тех пор, пока фильтр(элемент) не истинно, а затем выполняет обычный .get().
Разрешается воспользоваться внутренним представлением Queue
1 async def putter(n, queue):
2 for i in range(n):
3 await queue.put(i)
4
5 async def getter(n, queue, filter):
6 for i in range(n):
7 await asyncio.sleep(0.1)
8 yield await queue.get(filter)
9
10 async def main():
11 queue = FilterQueue(10)
12 asyncio.create_task(putter(20, queue))
13 async for res in getter(20, queue, lambda n: n % 2):
14 print(res)
15
16 asyncio.run(main())
Поскольку getter() работает с задержкой, а размер очереди ограничен 10 элементами, порядок работы такой:
- Формируется очередь 0…9, больше места нет
- 0 переставляется в конец, 1 возвращается
пока getter() ждёт, в конец очереди приезжает 10
- 2 переставляется в конец, 3 возвращается
пока getter() ждёт, в конец очереди приезжает 11
- …
- в какой-то момент понадобится переставить несколько четных элементов, чтобы добраться до нечётного
- …
- Когда в очереди остаётся единственный нечётный элемент 17, он находится и выводится, в очередь приезжает 18, и все элементы становятся чётными
- Тогда согласно условию, выводится первый элемент очереди (который в это время равен 4)
- При этом в очередь приезжает 19
- Этот 19 находится и выводится
- С этого момента очередь не пополняется, все элементы в ней чётные, выводятся в сложившемся порядке
1 3 5 7 9 11 13 15 17 4 19 12 6 16 8 14 0 10 2 18
Спойлер: