Sujet : Re: Await expressions
De : ram (at) *nospam* zedat.fu-berlin.de (Stefan Ram)
Groupes : comp.lang.pythonDate : 31. Jan 2024, 15:43:15
Autres entêtes
Organisation : Stefan Ram
Message-ID : <await-20240131154138@ram.dialup.fu-berlin.de>
References : 1
ram@zedat.fu-berlin.de (Stefan Ram) writes:
|await_expr ::= "await" primary
|Suspend the execution of coroutine on an awaitable object.
My ideas of language specifications are that they should
contain all the information to write an implementation of the
language. I am not sure whether the Python Language Reference
already fullfils this criterion. BUT I have made one step
in the direction of better understanding "await":
main.py
import dis
def f(): return g()
dis.dis( f )
print()
async def f(): return await g()
dis.dis( f )
sys.stdout
3 0 LOAD_GLOBAL 0 (g)
2 CALL_FUNCTION 0
4 RETURN_VALUE
8 0 LOAD_GLOBAL 0 (g)
2 CALL_FUNCTION 0
4 GET_AWAITABLE
6 LOAD_CONST 0 (None)
8 YIELD_FROM
10 RETURN_VALUE
. So, now it's down to finding documentation for the "GET_AWAITABLE"
and "YIELD_FROM" opcodes! One can guess that GET_AWAITABLE just gets
a kind of reference to the coroutine g. So the core of await must be
YIELD_FROM. Web:
|In Python 3.11 and above, the YIELD_FROM opcode is replaced
|by a SEND + YIELD_VALUE while loop, as documented in the
|SEND(target_delta).
. Oh, this seems to be a moving target!
|# yield from subgenerator is implemented as the following loop
|# (with None initially at the top of the stack)
|#
|# SEND (sends the top of stack to the subgenerator)
|# YIELD_VALUE (returns the yielded value to the caller)
|# JUMP_BACKWARDS (to SEND)
Ok, but this just seems to spell out what "YIELD_FROM" does,
so it should still be true that "await" boils down to "YIELD_FROM".
(Yes, Greg already kindly answered something to that effect.)