إنها مجموعة جديدة من النصائح والحيل حول Python والبرمجة من قناة Telegram-channelpythonetc.
← 
المنشورات السابقةbreak العبارة يمنع الاستثناء إذا تم استخدامه في الجملة الأخيرة حتى في حالة عدم تقديم الكتلة 
except :
 for i in range(10): try: 1 / i finally: print('finally') break print('after try') print('after while') 
الإخراج:
 finally after while 
وينطبق الشيء نفسه على 
continue ، ومع ذلك لا يمكن استخدامها في 
finally حتى بيثون 3.8:
 SyntaxError: 'continue' not supported inside 'finally' clause 
يمكنك إضافة أحرف Unicode في سلسلة حرفية ليس فقط برقمها ، ولكن أيضًا باسمها.
 >>> '\N{EM DASH}' '—' >>> '\u2014' '—' 
كما أنه متوافق مع سلاسل f:
 >>> width = 800 >>> f'Width \N{EM DASH} {width}' 'Width — 800' 
هناك ستة طرق سحرية لكائنات Python التي تحدد قواعد المقارنة:
- __lt__لـ- <
 
- __gt__لـ- >
 
- __le__لـ- <=
 
- __ge__لـ- >=
 
- __eq__لـ- ==
 
- __ne__- !=
 
إذا لم يتم تعريف بعض هذه الطرق أو إرجاع 
NotImplemented ، يتم تطبيق القواعد التالية:
- a.__lt__(b)هو نفسه- b.__gt__(a)
- a.__le__(b)هو نفس- b.__ge__(a)
- a.__eq__(b)هو نفسه- not a.__ne__(b)(ضع في اعتبارك أن- aو- bلا يتم تبديلهما في هذه الحالة)
ومع ذلك ، 
a >= b و 
a != b لا تعني تلقائيًا 
a > b . يقوم 
functools.total_ordering decorator بإنشاء جميع الطرق الست بناءً على 
__eq__ الطرق التالية: 
__lt__ أو 
__ge__ أو 
__ge__ أو 
__ge__ .
 from functools import total_ordering @total_ordering class User: def __init__(self, pk, name): self.pk = pk self.name = name def __le__(self, other): return self.pk <= other.pk def __eq__(self, other): return self.pk == other.pk assert User(2, 'Vadim') < User(13, 'Catherine') 
في بعض الأحيان تريد استخدام كل من الإصدارات المزخرفة وغير المزخرفة للدالة. أسهل طريقة لتحقيق ذلك هي التخلي عن بناء الديكور الخاص (الذي يحتوي على 
@ ) وإنشاء الوظيفة المزخرفة يدويًا:
 import json def ensure_list(f): def decorated(*args, **kwargs): result = f(*args, **kwargs) if isinstance(result, list): return result else: return [result] return decorated def load_data_orig(string): return json.loads(string) load_data = ensure_list(load_data_orig) print(load_data('3'))  
بدلاً من ذلك ، يمكنك كتابة ديكور آخر ، يزين وظيفة مع الحفاظ على نسخته الأصلية في السمة الأصلية للنسخة الجديدة:
 import json def saving_orig(another_decorator): def decorator(f): decorated = another_decorator(f) decorated.orig = f return decorated return decorator def ensure_list(f): ... @saving_orig(ensure_list) def load_data(string): return json.loads(string) print(load_data('3'))  
إذا تم إنشاء جميع أدوات الديكور التي تعمل معها عبر 
functools.wraps يمكنك استخدام سمة 
__wrapped__ للوصول إلى الوظيفة غير 
__wrapped__ :
 import json from functools import wraps def ensure_list(f): @wraps(f) def decorated(*args, **kwargs): result = f(*args, **kwargs) if isinstance(result, list): return result else: return [result] return decorated @ensure_list def load_data(string): return json.loads(string) print(load_data('3'))  
ومع ذلك ، 
__wrapped__ في 
__wrapped__ أنه لا يعمل في الوظائف التي تم تزيينها بواسطة أكثر من ديكور: يجب عليك الوصول إلى 
__wrapped__ كل) لكل تطبيق تم تطبيقه:
 def ensure_list(f): ... def ensure_ints(f): @wraps(f) def decorated(*args, **kwargs): result = f(*args, **kwargs) return [int(x) for x in result] return decorated @ensure_ints @ensure_list def load_data(string): return json.loads(string) for f in ( load_data, load_data.__wrapped__, load_data.__wrapped__.__wrapped__, ): print(repr(f('"4"'))) 
الإخراج:
 [4] ['4'] '4' 
يقبل 
@saving_orig المذكور أعلاه 
@saving_orig آخر كوسيطة. ماذا لو كان هذا الديكور يمكن أن يكون parametrized؟ حسنًا ، نظرًا لأن الديكور ذي المعلمات هو وظيفة تقوم بإرجاع ديكور فعلي ، يتم التعامل مع هذه الحالة تلقائيًا:
 import json from functools import wraps def saving_orig(another_decorator): def decorator(f): decorated = another_decorator(f) decorated.orig = f return decorated return decorator def ensure_ints(*, default=None): def decorator(f): @wraps(f) def decorated(*args, **kwargs): result = f(*args, **kwargs) ints = [] for x in result: try: x_int = int(x) except ValueError: if default is None: raise else: x_int = default ints.append(x_int) return ints return decorated return decorator @saving_orig(ensure_ints(default=0)) def load_data(string): return json.loads(string) print(repr(load_data('["2", "3", "A"]'))) print(repr(load_data.orig('["2", "3", "A"]'))) 
لا يقوم مصمم الديكور 
@saving_orig بعمل ما نريد إذا كان هناك أكثر من ديكور يطبق على وظيفة ما. علينا أن ندعو 
orig لكل ديكور:
 import json from functools import wraps def saving_orig(another_decorator): def decorator(f): decorated = another_decorator(f) decorated.orig = f return decorated return decorator def ensure_list(f): ... def ensure_ints(*, default=None): ... @saving_orig(ensure_ints(default=42)) @saving_orig(ensure_list) def load_data(string): return json.loads(string) for f in ( load_data, load_data.orig, load_data.orig.orig, ): print(repr(f('"X"'))) 
الإخراج:
 [42] ['X'] 'X' 
يمكننا إصلاحه من خلال دعم العدد التعسفي من الديكورات 
saving_orig :
 def saving_orig(*decorators): def decorator(f): decorated = f for d in reversed(decorators): decorated = d(decorated) decorated.orig = f return decorated return decorator ... @saving_orig( ensure_ints(default=42), ensure_list, ) def load_data(string): return json.loads(string) for f in ( load_data, load_data.orig, ): print(repr(f('"X"'))) 
الإخراج:
 [42] 'X' 
هناك حل آخر وهو جعل 
saving_orig ذكيًا بما يكفي لتمرير 
orig من وظيفة مزينة إلى أخرى:
 def saving_orig(another_decorator): def decorator(f): decorated = another_decorator(f) if hasattr(f, 'orig'): decorated.orig = f.orig else: decorated.orig = f return decorated return decorator @saving_orig(ensure_ints(default=42)) @saving_orig(ensure_list) def load_data(string): return json.loads(string) 
إذا أصبح الديكور الذي تكتبه معقدًا جدًا ، فقد يكون من المعقول تحويله من وظيفة إلى فصل باستخدام طريقة 
__call__ class SavingOrig: def __init__(self, another_decorator): self._another = another_decorator def __call__(self, f): decorated = self._another(f) if hasattr(f, 'orig'): decorated.orig = f.orig else: decorated.orig = f return decorated saving_orig = SavingOrig 
السطر الأخير يسمح لكما بتسمية الصف مع حقيبة الهجن والحفاظ على اسم الديكور في حالة الثعبان.
بدلاً من تعديل الوظيفة المزخرفة ، يمكنك إنشاء فئة أخرى قابلة للاستدعاء لإرجاع مثيلاتها بدلاً من دالة:
 class CallableWithOrig: def __init__(self, to_call, orig): self._to_call = to_call self._orig = orig def __call__(self, *args, **kwargs): return self._to_call(*args, **kwargs) @property def orig(self): if isinstance(self._orig, type(self)): return self._orig.orig else: return self._orig class SavingOrig: def __init__(self, another_decorator): self._another = another_decorator def __call__(self, f): return CallableWithOrig(self._another(f), f) saving_orig = SavingOrig 
عرض الكود كله 
هنا