8.10. Kelas awaitable¶
8.10.1. Apa itu awaitable¶
Ketika sebuah coroutine menulis await x, bahasa bertanya kepada x bagaimana cara menunggunya. Objek apa pun yang tahu cara menjawab adalah awaitable. Ada dua jenisnya:
Objek coroutine yang dikembalikan oleh fungsi
async def. Memanggilsend_request()menghasilkan salah satunya setiap kali -- objek coroutine, bukan hasil fungsi. Menulisawait send_request()adalah yang benar-benar menjalankan isi fungsi.Objek dari kelas yang mendefinisikan metode
__await__.async defadalah singkatan untuk jenis pertama;__await__adalah cara manual untuk membuat jenis kedua.
Kode aplikasi menggunakan jenis pertama secara default. Jenis kedua ada untuk kasus langka di mana objek itu sendiri perlu menjadi sesuatu yang di-await oleh pemanggil, bukan hasil dari memanggil metode pada objek tersebut.
8.10.2. Dua bentuk secara berdampingan¶
Logika yang sama ditulis sebagai coroutine dan sebagai kelas awaitable:
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
Keduanya dapat di-await dengan cara yang sama:
async def main():
a = await yield_then_return(1)
b = await YieldThenReturn(2)
print(a, b) # prints: 1 2
Bentuk async def lebih pendek, terbaca seperti Python biasa, dan membiarkan bahasa mengelola semua pembukuan suspend-dan-resume. Bentuk kelas tidak mendapat tambahan apa pun dalam contoh ini.
8.10.3. Kapan bentuk kelas diperlukan¶
Ketika objek harus menjadi sesuatu yang diserahkan oleh aplikasi -- bukan fungsi yang dipanggil pemanggil untuk mendapatkan coroutine -- bentuk kelas adalah satu-satunya pilihan:
Nilai future-like yang dibuat aplikasi, diserahkan ke produsen, dan di-
awaitnanti untuk mengambil hasil yang diproduksi.Primitif kustom yang dibangun di atas primitif yang ada di mana API alaminya adalah
await my_thingbukanawait my_thing.wait(). Kelasasyncio.Taskitu sendiri adalah contoh bawaan -- menulisawait taskberfungsi karenaTaskmendefinisikan__await__.
Untuk apa pun yang sesuai dengan bentuk panggil fungsi, dapatkan coroutine, await-nya, async def menang.
8.10.4. Detail protokol¶
__await__ adalah metode biasa (bukan async def) yang mengembalikan sebuah iterator. Menulisnya sebagai generator -- termasuk setidaknya satu yield dalam isi -- membuatnya menjadi iterator secara otomatis. Setiap yield menangguhkan coroutine yang me-await objek dan menyerahkan kontrol kembali ke event loop; generator dilanjutkan saat berikutnya loop menjadwalkan task. return kosong (atau akhir fungsi) mengakhiri penantian; apa pun yang dihasilkan return menjadi nilai dari ekspresi await.
Dalam praktiknya, kelas langka yang melakukan ini menyerahkan yielding ke awaitable yang ada daripada menggerakkan loop sendiri:
class WaitForEvent:
def __init__(self, event):
self._event = event
def __await__(self):
yield from self._event.wait().__await__()
return self._event
yield from menggunakan kembali __await__ event yang mendasarinya untuk penangguhan yang sebenarnya. Sebagian besar aplikasi asyncio tidak pernah perlu menulis salah satu bentuk tersebut.