تضمين التغريدةPythonetc سبتمبر 2019



مجموعة جديدة من نصائح 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('') # never happens loop = asyncio.get_event_loop() run = loop.run_until_complete task = loop.create_task(printer()) run(asyncio.sleep(1)) # printer works here print('||') run(asyncio.sleep(1)) # printer works here task.cancel() # nothing happens run(asyncio.sleep(1)) #  printed 

النتيجة:

 * * || *  

تأكد من الانتظار حتى تكتمل جميع المهام قبل إيقاف الدورة. إذا لم يتم ذلك ، فيمكنك تخطي بعض الكتل 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)) # 2.0 print(sqrt_abs2(-4)) # 2.0 


عند تعريف فئة ، يمكنك تمرير الوسائط إلى ملف التعريف الخاص بها. يدعم تدوين 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) # 2 print(a.half_of_100) # 50 a.half # AttributeError 


في بعض الأحيان تحتاج إلى استنفاد المولد ، ولكن في نفس الوقت لا تهتم بالقيم التي ينشئها ، ولكن في بعض الآثار الجانبية. على سبيل المثال ، استثناء ، الكتابة إلى ملف ، تغيير متغير عمومي ، إلخ.

هناك طريقة مريحة وشائعة للقيام بذلك هي 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) 

تسمى الفصول التي ليست متغيرة ولا متنافرة ثابتة .

Source: https://habr.com/ru/post/ar470109/


All Articles