
مجموعة جديدة من نصائح Python والبرمجة من خلال موجز pythonetc الخاص بي.
←
المجموعات السابقةفي
asyncio
لا يلزم بدء حلقة لاحتواء المهام. يمكنك إنشاء وإيقاف المهام حتى عند إيقاف الدورة. إذا تم إيقافه ، فقد تظل بعض المهام غير مكتملة.
import asyncio async def printer(): try: try: while True: print('*') await asyncio.sleep(1) except asyncio.CancelledError: print('') finally: await asyncio.sleep(2) print('')
النتيجة:
* * || *
تأكد من الانتظار حتى تكتمل جميع المهام قبل إيقاف الدورة. إذا لم يتم ذلك ، فيمكنك تخطي بعض الكتل
finally
ولن يتم تعطيل بعض مديري السياق.
يسمح لك Python بتجاوز العديد من المشغلين ، بما في ذلك مشغل التحول bitwise. فيما يلي مثال على إنشاء مجموعة من الوظائف باستخدام عامل التشغيل هذا. تشير الأسهم إلى اتجاه نقل البيانات:
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))
عند تعريف فئة ، يمكنك تمرير الوسائط إلى ملف التعريف الخاص بها. يدعم تدوين
class
الكلمات الأساسية كوسائط:
class Klass(Parent, arg='arg')
. الكلمة الأساسية لـ metaclass محجوزة لاختيار metaclass ، ويمكنك استخدام الآخرين كما يحلو لك.
فيما يلي مثال على ملف التعريف الذي يقوم بإنشاء فصل بدون إحدى السمات. يتم توفير اسم السمة في وسيطة
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)
في بعض الأحيان تحتاج إلى استنفاد المولد ، ولكن في نفس الوقت لا تهتم بالقيم التي ينشئها ، ولكن في بعض الآثار الجانبية. على سبيل المثال ، استثناء ، الكتابة إلى ملف ، تغيير متغير عمومي ، إلخ.
هناك طريقة مريحة وشائعة للقيام بذلك هي
list(gen())
. ومع ذلك ، فإن هذا الأسلوب يحفظ جميع القيم في الذاكرة ، ثم يحذفها على الفور. هذا قد يكون زائدا. إذا كنت ترغب في تجنب هذا السلوك ، يمكنك استخدام
deque
مع حد الحجم:
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')
من أجل الدقة الدلالية ، يمكنك تحديد وظيفة
exhaust
الخاصة بك:
def exhaust(iterable): for _ in iterable: pass
افترض أن لديك فصلين - الطفل الأصل ،
User
والمسؤول. ولديك أيضًا وظيفة تأخذ قائمة المستخدمين كوسيطة. يمكنك تقديم قائمة من مدراء؟ لا: يمكن أن تضيف الوظيفة مستخدمًا آخر إلى قائمة المشرفين ، والتي تعتبر خاطئة وتنتهك الضمانات التي توفرها القائمة.
ومع ذلك ، يمكنك توفير نوع
Sequence
لأنه للقراءة فقط. بتعبير أدق ، في هذه الحالة ، يكون
Sequence
متغايرًا في نوع المشاركين.
يمكنك تعريف أنواع المتغيرات عن طريق توفير
covariant=True
كوسيطة لـ
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)
على العكس ، قد تتطلب الوظيفة حاوية فقط لوضع مدراء بها. مثل هذه الحاويات ، المتاحة للتسجيل فقط ،
تتعارض مع نوع المشاركين:
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)
تسمى الفصول التي ليست متغيرة ولا متنافرة
ثابتة .