# 11.8 异步生成器

到目前为止你学到的生成器和协程的概念，可以组合成**异步生成器**。

如果一个函数使用 `async` 关键字声明并包含 `yield` 语句，那么它在调用时会转换为异步生成器对象。

与生成器一样，异步生成器必须由能理解协议的东西执行。异步生成器有一个 `__anext__()` 方法来代替生成器中的 `__next__()` 方法。

常规的 `for` 循环无法理解异步生成器，因此你可以使用 `async for` 语句代替。

你可以将 `check_port()` 重构为一个异步生成器，该生成器会生成下一个打开的端口，直到它到达最后一个端口或找到指定数量的打开端口为止：

```python
async def check_ports(host: str, start: int, end: int, max=10):
    found = 0
    for port in range(start, end):
        try:
            future = asyncio.open_connection(host=host, port=port)
            r, w = await asyncio.wait_for(future, timeout=timeout)
            yield port
            found += 1
            w.close()
            if found >= max:
                return
        except asyncio.TimeoutError:
            pass # Closed
```

要执行此操作，请使用 `async for` 语句：

```python
async def scan(start, end, host):
    results = []
    async for port in check_ports(host, start, end, max=1):
        results.append(port)
    return results
```

完整示例请参阅 `cpython-book-sa​​mples/33/portscanner_async_generators.py`。
