Как функция Python может стать эффективной до того, как ее параметр будет оценен следующим образом? - PullRequest
0 голосов
/ 19 марта 2020

Посмотрите следующий код:

import asyncio

async def count():
    print("One")
    await asyncio.sleep(1)
    print("Two")

async def main():
    await asyncio.gather(count(), count(), count())  # THIS LINE

if __name__ == "__main__":
    import time
    s = time.perf_counter()
    asyncio.run(main())
    elapsed = time.perf_counter() - s
    print(f"{__file__} executed in {elapsed:0.2f} seconds.")

Посмотрите на # THIS LINE, asyncio.gather может выполнить свою функцию до возвращаемого значения параметра count ().

Но, как я понимаю python. Интерпретатор python считает внешнюю функцию черным ящиком и вначале сосредотачивается на оценке ее параметра. Когда все значение его параметра выполнено, интерпретатор затем передает его в функцию для выполнения.

Согласно моему пониманию выше, не будет разницы между:

await asyncio.gather(count(), count(), count())

и

await (count(), count(), count())

Последующим является неназначенный кортеж.

Но как asyncio.gather реализует свои задания в такой форме?

1 Ответ

1 голос
/ 19 марта 2020

Поскольку функция count определяется как async def count():, при ее вызове вместо выполнения функции она возвращает объект сопрограммы.

Сопрограмма (например, count) начинает выполнять только при использовании await на нем. Способ выражения await count() оценивается следующим образом:

  1. count вызывается, возвращая сопрограмму.
  2. await начинает ожидание в сопрограмме.
  3. сопрограмма выполняется, возвращая None (потому что функция count ничего не возвращает)
  4. выражение await count() возвращает None.

Итак, в вашем примере - при выполнении await asyncio.gather(count(), count(), count()):

  1. count вызывается три раза, возвращая 3 различных сопрограммы.
  2. Эти сопрограммы передаются в качестве параметров asyncio.gather.
  3. asyncio.gather само возвращает сопрограмму.
  4. await ожидает на asyncio.gather, что ожидает всех сопрограмм с параметрами.

Второе выражение, await (count(), count(), count()) won не работает, так как вы не можете использовать await для чего-то, что не является сопрограммой.

...