هذه هي المجموعة العاشرة من نصائح Python والبرمجة من خلاصتي @ pythonetc.
التحديدات السابقة .
0_0
0_0 تعبير صحيح تمامًا في Python.
فرز القائمة مع لا شيء
يمكن أن يكون تصنيف قائمة ذات قيم بلا مهمة شاقة:
 In [1]: data = [  ...: dict(a=1),  ...: None,  ...: dict(a=-3),  ...: dict(a=2),  ...: None,  ...: ] In [2]: sorted(data, key=lambda x: x['a']) ... TypeError: 'NoneType' object is not subscriptable 
يمكنك محاولة حذف الكل بلا وإعادتها مرة أخرى بعد الفرز (إلى بداية القائمة أو نهايتها ، حسب المهمة):
 In [3]: sorted(  ...: (d for d in data if d is not None),  ...: key=lambda x: x['a']  ...: ) + [  ...: d for d in data if d is None  ...: ] Out[3]: [{'a': -3}, {'a': 1}, {'a': 2}, None, None] 
لكنه غير مريح. استخدام أفضل 
key أكثر تعقيدًا:
 In [4]: sorted(data, key=lambda x: float('inf') if x is None else x['a']) Out[4]: [{'a': -3}, {'a': 1}, {'a': 2}, None, None] 
إذا كنا نتحدث عن الأنواع التي لا تقبل اللانهاية لها ، فيمكنك فرز المجموعات:
 In [5]: sorted(data, key=lambda x: (1, None) if x is None else (0, x['a'])) Out[5]: [{'a': -3}, {'a': 1}, {'a': 2}, None, None] 
الاتصال عشوائي. البذور ()
عندما تتفرع من العملية ، سيتم نسخ البذور العشوائية التي تستخدمها لجميع العمليات الناتجة. نتيجة لذلك ، يمكن إنشاء نفس النتيجة "العشوائية" فيها.
لتجنب ذلك ، تحتاج إلى الاتصال 
random.seed() في كل عملية. ولكن إذا كنت تستخدم وحدة 
multiprocessing ، فستقوم 
بذلك نيابة عنك.
على سبيل المثال:
 import multiprocessing        import random                 import os                     import sys                    def test(a):                  print(random.choice(a), end=' ') a = [1, 2, 3, 4, 5]           for _ in range(5):            test(a)                   print()                       for _ in range(5):            p = multiprocessing.Process(   target=test, args=(a,) )                         p.start()                 p.join()                  print()                       for _ in range(5):            pid = os.fork()           if pid == 0:              test(a)               sys.exit()            else:                     os.wait()             print() 
احصل على شيء مثل هذا:
 4 4 4 5 5 1 4 1 3 3 2 2 2 2 2 
علاوة على ذلك ، إذا كنت تستخدم Python 3.7 وما فوق ، فبفضل 
at_fork الجديد at_fork يمكنك أن تفعل 
الشيء نفسه باستخدام 
os.fork .
يعطي رمز Python 3.7 أعلاه هذه النتيجة:
 1 2 2 1 5 4 4 4 5 5 2 4 1 3 1 
إضافة إلى 0
للوهلة الأولى ، يبدو أن 
sum([a, b, c]) مكافئ لـ 
a + b + c ، على الرغم من أن المعادل سيكون 
0 + a + b + c . لذلك لا يمكن أن يعمل هذا التعبير مع الأنواع التي لا تدعم إضافة إلى 
0 :
 class MyInt: def __init__(self, value): self.value = value def __add__(self, other): return type(self)(self.value + other.value) def __radd__(self, other): return self + other def __repr__(self): class_name = type(self).__name__ return f'{class_name}({self.value})' In : sum([MyInt(1), MyInt(2)]) ... AttributeError: 'int' object has no attribute 'value' 
لإصلاح ذلك ، يمكنك توفير عنصر بدء مخصص سيتم استخدامه بدلاً من 
0 :
 In : sum([MyInt(1), MyInt(2)], MyInt(0)) Out: MyInt(3) 
sum تصميم 
sum لإضافة أنواع 
float و 
int ، على الرغم من أنه يمكن أن يعمل مع أي أنواع مخصصة أخرى. ومع ذلك ، فهو يرفض إضافة 
bytes ، و 
bytearray و 
str ، لأن الصلة 
join لهذا الغرض:
 In : sum(['a', 'b'], '') ... TypeError: sum() can't sum strings [use ''.join(seq) instead] In : ints = [x for x in range(10_000)] In : my_ints = [Int(x) for x in ints] In : %timeit sum(ints) 68.3 µs ± 142 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each) In : %timeit sum(my_ints, Int(0)) 5.81 ms ± 20.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 

إكمال الفهرس في دفتر Jupyter
باستخدام طريقة 
_ipython_key_completions_ ، 
_ipython_key_completions_ تخصيص إكمال الفهرس في Jupyter Notebook. وبهذه الطريقة يمكنك التحكم في ما يتم عرضه على الشاشة إذا قمت بالضغط على Tab بعد شيء مثل 
d["x :

لاحظ أن الأسلوب لا يتلقى السلسلة التي سيتم البحث فيها كوسيطة.