
Ini adalah pilihan baru tips dan trik tentang Python dan pemrograman dari saluran-Telegram saya @pythonetc.
←
Publikasi sebelumnyaloop
asyncio
tidak harus dijalankan untuk memiliki tugas. Anda dapat membuat dan menghentikan tugas meskipun loop dihentikan sekarang. Jika loop dihentikan, beberapa tugas mungkin tidak selesai untuk selamanya.
import asyncio async def printer(): try: try: while True: print('*') await asyncio.sleep(1) except asyncio.CancelledError: print('x') finally: await asyncio.sleep(2) print('o')
Keluaran:
* * || * x
Anda harus yakin untuk menunggu semua tugas sebelum menghentikan loop. Jika Anda tidak, Anda mungkin memiliki beberapa blok
finally
dilewati dan beberapa manajer konteks tidak keluar.
Python memungkinkan Anda membebani banyak operator yang berbeda dan operator shift adalah salah satunya. Berikut adalah contoh cara membuat komposisi fungsi menggunakan operator ini. Di sini, tanda panah seperti menunjukkan arah aliran data:
from collections import deque from math import sqrt class Compose: def __init__(self): self._functions = deque() def __call__(self, *args, **kwargs): result = None for f in self._functions: result = f(*args, **kwargs) args = [result] kwargs = dict() return result def __rshift__(self, f): self._functions.append(f) return self def __lshift__(self, f): self._functions.appendleft(f) return self compose = Compose sqrt_abs = (compose() << sqrt << abs) sqrt_abs2 = (compose() >> abs >> sqrt) print(sqrt_abs(-4))
Anda bisa meneruskan argumen ke metaclass khusus dari definisi kelas. Notasi
class
mendukung argumen kata kunci:
class Klass(Parent, arg='arg')
. Kata kunci
metaclass
dicadangkan untuk mengatur metaclass, tetapi yang lain bebas untuk digunakan.
Berikut ini adalah contoh dari metaclass yang menciptakan kelas tanpa salah satu atribut. Nama atribut itu disediakan dalam argumen
remove
:
class FilterMeta(type): def __new__(mcs, name, bases, namespace, remove=None, **kwargs): if remove is not None and remove in namespace: del namespace[remove] return super().__new__(mcs, name, bases, namespace) class A(metaclass=FilterMeta, remove='half'): def half(x): return x // 2 half_of_4 = half(4) half_of_100 = half(100) a = A() print(a.half_of_4)
Terkadang Anda ingin menghabiskan generator, tetapi Anda tidak peduli dengan nilai yang dihasilkannya. Anda peduli tentang beberapa efek samping, mungkin pengecualian, menulis ke file, modifikasi variabel global dll.
Cara yang mudah dan banyak digunakan untuk melakukan ini adalah
list(gen())
. Namun, kode ini menyimpan semua nilai ke dalam memori hanya untuk membuangnya segera setelahnya. Itu bisa tidak diinginkan.
Jika Anda ingin menghindari ini, Anda dapat menggunakan
deque
dengan ukuran terbatas sebagai gantinya:
from collections import deque def inversed(nums): for num in nums: yield 1 / num try: deque(inversed([1, 2, 0]), maxlen=0) except ZeroDivisionError: print('E')</code> To be more semantically precise you better define your own <code>exhaust</code> function: <source lang="python"> def exhaust(iterable): for _ in iterable: pass
Bayangkan Anda memiliki sepasang kelas yang merupakan induk dan anak, katakanlah
User
dan
Admin
. Anda juga memiliki fungsi yang mengambil daftar pengguna sebagai argumen. Bisakah Anda memberikan daftar admin? Jawabannya adalah tidak: fungsi dapat menambahkan pengguna lain ke daftar admin yang tidak valid dan melanggar jaminan yang disediakan daftar.
Namun, Anda dapat memberikan
Sequence
admin karena
Sequence
hanya baca. Istilah yang tepat di sini adalah
Sequence
kovarian pada tipe anggotanya.
Anda dapat mendefinisikan tipe kovarian dengan memberikan
covariant=True
sebagai argumen
TypeVar
:
from typing import TypeVar, Generic T = TypeVar('T', covariant=True) class Holder(Generic[T]): def __init__(self, var: T): self._var: T = var def get(self) -> T: return self._var class User: pass class Admin(User): pass def print_user_from_holder(holder: Holder[User]) -> None: print(holder.get()) h: Holder[Admin] = Holder(Admin()) print_user_from_holder(h)
Sebaliknya, fungsi mungkin memerlukan wadah hanya untuk menempatkan admin di sana. Wadah hanya-tulis semacam itu bersifat
contravarian pada jenis anggotanya:
from typing import TypeVar, Generic T = TypeVar('T', contravariant=True) class Holder(Generic[T]): def __init__(self, var: T): self._var: T = var def change(self, x: T): self._var = x class User: pass class Admin(User): pass def place_admin_to_holder(holder: Holder[Admin]) -> None: holder.change(Admin()) h: Holder[User] = Holder(User()) place_admin_to_holder(h)
Kelas yang bukan kovarian atau contravarian disebut
invarian .