8.10. Await edilebilir sınıflar¶
8.10.1. Await edilebilir nedir¶
Bir eşyordam await x yazdığında, dil x nesnesine onu nasıl bekleyeceğini sorar. Bu soruya nasıl yanıt vereceğini bilen her nesne await edilebilirdir. İki türü vardır:
async deffonksiyonlarının döndürdüğü eşyordam nesneleri.send_request()çağrısı her seferinde bunlardan birini – fonksiyonun sonucunu değil, eşyordam nesnesini – üretir.await send_request()yazmak gövdeyi gerçekten çalıştıran şeydir.Bir
__await__metodu tanımlayan bir sınıfın nesneleri.async defilk türün kısayoludur;__await__ise ikinci türü oluşturmanın elle yapılan yoludur.
Uygulama kodu varsayılan olarak ilk türü kullanır. İkinci tür, çağıranın bir metodu çağırmasının sonucunu değil, nesnenin kendisinin await edilecek şey olması gerektiği nadir durumlar için vardır.
8.10.2. İki biçim yan yana¶
Aynı mantığın hem bir eşyordam hem de bir await edilebilir sınıf olarak yazılışı:
import asyncio
# async def -- almost always the right choice
async def yield_then_return(value):
await asyncio.sleep_ms(0)
return value
# awaitable class -- equivalent, rarely written
class YieldThenReturn:
def __init__(self, value):
self._value = value
def __await__(self):
yield # let the loop run once
return self._value # value of the ``await`` expression
Her ikisi de aynı şekilde await edilebilir:
async def main():
a = await yield_then_return(1)
b = await YieldThenReturn(2)
print(a, b) # prints: 1 2
async def biçimi daha kısadır, normal Python gibi okunur ve tüm askıya alma ve devam ettirme defter tutmasını dilin yönetmesini sağlar. Bu örnekte sınıf biçimi fazladan hiçbir şey kazandırmaz.
8.10.3. Sınıf biçiminin yerini hak ettiği durum¶
Nesnenin, çağıranın bir eşyordam elde etmek için çağırdığı bir fonksiyon değil de, uygulamanın etrafta dolaştırdığı bir şey olması gerektiğinde, tek seçenek sınıf biçimidir:
Uygulamanın oluşturduğu, bir üreticiye verdiği ve üretilen sonucu almak için daha sonra
awaitettiği future benzeri bir değer.Doğal API’nin
await my_thing.wait()yerineawait my_thingolduğu, mevcut bir ilkel üzerine inşa edilmiş özel bir ilkel.asyncio.Tasksınıfının kendisi yerleşik bir örnektir –await taskyazmak çalışır çünküTaskbir__await__tanımlar.
Bir fonksiyon çağır, bir eşyordam al, onu await et biçimine uyan her şey için async def kazanır.
8.10.4. Protokol ayrıntıları¶
__await__, bir yineleyici döndüren sıradan bir metottur (async def değil). Onu bir üreteç olarak yazmak – gövdede en az bir yield bulundurmak – onu otomatik olarak bir üretece dönüştürür. Her yield, nesneyi await eden eşyordamı askıya alır ve kontrolü olay döngüsüne geri verir; döngü görevi bir sonraki kez zamanladığında üreteç devam eder. Çıplak bir return (ya da sona ulaşmak) beklemeyi bitirir; return‘ün ürettiği her ne ise await ifadesinin değeri olur.
Uygulamada bunu yapan nadir sınıf, döngüyü kendisi sürmek yerine yield etmeyi mevcut bir await edilebilire devreder:
class WaitForEvent:
def __init__(self, event):
self._event = event
def __await__(self):
yield from self._event.wait().__await__()
return self._event
yield from, gerçek askıya alma işlemi için alttaki olayın __await__ metodunu yeniden kullanır. Çoğu asyncio uygulamasının bu biçimlerden herhangi birini yazmaya hiç ihtiyacı olmaz.