نصائح مفيدة بايثون لم تقابل

تمت كتابة العديد من المقالات حول ميزات Python المثيرة للاهتمام. إنهم يتحدثون عن تفريغ القوائم و tuples في المتغيرات ، حول التطبيق الجزئي للوظائف ، حول العمل مع الأشياء القابلة للتكرار. لكن في بيثون هناك الكثير. يقول مؤلف المقال الذي نترجمه اليوم إنه يريد التحدث عن بعض ميزات بيثون التي يستخدمها. في الوقت نفسه ، لم يواجه بعد وصفًا لهذه الاحتمالات ، على غرار تلك الواردة هنا. من المحتمل أنك لم تقرأ عنها في أي مكان آخر.



مسح بيانات سلسلة الإدخال


مهمة تنظيف البيانات المدخلة من قبل المستخدم ذات صلة بأي برنامج تقريبًا. غالبًا ما تأتي معالجة الإدخال هذه لتحويل الأحرف إلى أحرف كبيرة أو صغيرة. في بعض الأحيان يمكن مسح البيانات باستخدام تعبير عادي. ولكن في الحالات التي تكون فيها المهمة معقدة ، يمكنك تطبيق طريقة أكثر نجاحًا لحلها. على سبيل المثال - هذا:

user_input = "This\nstring has\tsome whitespaces...\r\n" character_map = {  ord('\n') : ' ',  ord('\t') : ' ',  ord('\r') : None } user_input.translate(character_map) # This string has some whitespaces... " 

هنا يمكنك أن ترى كيف يتم استبدال الأحرف البيضاء "\n" و "\t" بمسافات عادية ، وكيف تتم إزالة الحرف "\r" بالكامل من السلسلة. هذا مثال بسيط ، ولكن يمكننا تمديده عن طريق إنشاء جداول كبيرة لإعادة تعيين الأحرف باستخدام حزمة unicodedata ووظائفها unicodedata combining() . تسمح لك هذه الطريقة بإزالة كل ما هو غير ضروري هناك من الخطوط.

الحصول على شرائح التكرار


إذا حاولت الحصول على شريحة من التكرار ، TypeError خطأ في TypeError ، مما يشير إلى أنه لا يمكنك الاشتراك في كائن المولد. ومع ذلك ، يمكن حل هذه المشكلة:

 import itertools s = itertools.islice(range(50), 10, 20) # <itertools.islice object at 0x7f70fab88138> for val in s: ... 

باستخدام طريقة itertools.islice ، itertools.islice إنشاء كائن islice ، وهو مكرر يقوم islice العناصر الضرورية. ومع ذلك ، من المهم أن نلاحظ هنا أن هذا البناء يستخدم جميع عناصر المولد حتى بداية الشريحة وجميع العناصر الموجودة في كائن islice .

تخطي بداية الكائن القابل للتكرار


في بعض الأحيان تحتاج إلى العمل مع ملف ، كما تعلمون ، يبدأ بعدد معين من الخطوط غير الضرورية - مثل الخطوط التي تحتوي على تعليقات. لتخطي هذه الخطوط ، يمكنك اللجوء مرة أخرى إلى itertools :

 string_from_file = """ // Author: ... // License: ... // // Date: ... Actual content... """ import itertools for line in itertools.dropwhile(lambda line: line.startswith("//"), string_from_file.split("\n")): print(line) 

هذا الرمز فقط إرجاع الأسطر بعد كتلة التعليقات الموجودة في بداية الملف. قد يكون هذا النهج مفيدًا عندما تحتاج إلى تجاهل العناصر فقط (في حالتنا ، الأسطر) في بداية الكائن القابل للتكرار ، لكن رقمهم الدقيق غير معروف.

وظائف تدعم الوسائط المسماة فقط (kwargs)


لجعل ذلك ممكنًا عند استخدام دالة معينة بحيث يمكن تمرير الوسائط المسماة فقط إليها ، يمكنك القيام بما يلي:

 def test(*, a, b): pass test("value for a", "value for b") # TypeError: test() takes 0 positional arguments... test(a="value", b="value 2") #   - ... 

يمكن أن يكون هذا مفيدًا لتحسين فهم الكود. كما ترون ، يمكن حل مشكلتنا بسهولة باستخدام الوسيطة * أمام قائمة الوسائط المسماة. هنا ، وهو أمر واضح تمامًا ، يمكنك أيضًا استخدام الوسيطات الموضعية - إذا قمت بوضعها قبل الوسيطة * .

إنشاء الكائنات التي تدعم العبارة


يعلم الجميع كيف ، على سبيل المثال ، فتح ملف ، أو ، ربما ، كيفية تعيين قفل باستخدام العبارة ب. ولكن هل من الممكن تنفيذ آلية التحكم في القفل بشكل مستقل؟ نعم ، هذا حقيقي جدا. يتم تطبيق بروتوكول إدارة سياق التنفيذ باستخدام أساليب __exit__ و __exit__ :

 class Connection: def __init__(self):  ... def __enter__(self):  #  ... def __exit__(self, type, value, traceback):  #  ... with Connection() as c: # __enter__() executes ... # conn.__exit__() executes 

هذه هي الطريقة الأكثر شيوعًا لتنفيذ قدرات مدير السياق في بيثون ، ولكن نفس الشيء يمكن القيام به بسهولة:

 from contextlib import contextmanager @contextmanager def tag(name): print(f"<{name}>") yield print(f"</{name}>") with tag("h1"): print("This is Title.") 

هنا ، يتم تطبيق بروتوكول إدارة السياق باستخدام أداة contextmanager السياق. يتم تنفيذ الجزء الأول من وظيفة tag (قبل yield ) عند إدخال الكتلة with . ثم يتم تنفيذ هذا الحظر ، وبعد ذلك يتم تنفيذ ما تبقى من وظيفة tag .

حفظ الذاكرة مع __slots__


إذا سبق لك أن كتبت برامج تنشئ أعدادًا كبيرة جدًا من مثيلات فئة معينة ، فقد تلاحظ أن هذه البرامج قد تتطلب ذاكرة كبيرة بشكل غير متوقع. هذا لأن بايثون يستخدم القواميس لتمثيل سمات حالات الفصل. هذا له تأثير جيد على الأداء ، ولكن من حيث استهلاك الذاكرة ، فإنه غير فعال. عادة ، ومع ذلك ، لا تسبب هذه الميزة مشاكل. ومع ذلك ، إذا كنت تواجه نقصًا في الذاكرة في موقف مشابه ، فيمكنك محاولة استخدام سمة __slots__ :

 class Person: __slots__ = ["first_name", "last_name", "phone"] def __init__(self, first_name, last_name, phone):  self.first_name = first_name  self.last_name = last_name  self.phone = phone 

هنا ، عندما نعلن عن سمة __slots__ ، يستخدم Python مجموعة صغيرة ذات حجم ثابت لتخزين السمات ، وليس القاموس. هذا يقلل بشكل خطير مقدار الذاكرة المطلوبة لكل مثيل للفئة. هناك بعض العيوب لاستخدام السمة __slots__ . لذلك ، باستخدامه ، لا يمكننا الإعلان عن سمات جديدة ، فنحن __slots__ فقط على تلك الموجودة في __slots__ . بالإضافة إلى ذلك ، لا يمكن للفئات ذات السمة __slots__ استخدام الوراثة المتعددة.

وحدة المعالجة المركزية وحدود الذاكرة


إذا بدلاً من تحسين البرنامج ، أو تحسين الطريقة التي يستخدم بها المعالج ، فأنت بحاجة فقط إلى وضع قيود صارمة على الموارد المتاحة له ، يمكنك استخدام المكتبة المناسبة:

 import signal import resource import os #     def time_exceeded(signo, frame): print("CPU exceeded...") raise SystemExit(1) def set_max_runtime(seconds): #   signal     soft, hard = resource.getrlimit(resource.RLIMIT_CPU) resource.setrlimit(resource.RLIMIT_CPU, (seconds, hard)) signal.signal(signal.SIGXCPU, time_exceeded) #     def set_max_memory(size): soft, hard = resource.getrlimit(resource.RLIMIT_AS) resource.setrlimit(resource.RLIMIT_AS, (size, hard)) 

هذا يدل على الحد من وقت المعالج وحجم الذاكرة. للحد من استخدام البرنامج للمعالج ، نحصل أولاً على قيم غير صلبة (ناعمة) وحدود صلبة (صلبة) لمورد معين ( RLIMIT_CPU ). ثم نقوم بتعيين الحد باستخدام عدد معين من الثواني المحدد بواسطة وسيطة seconds وقيمة الحد الثابت التي تم الحصول عليها مسبقًا. بعد ذلك ، نسجل معالج signal ، الذي ، عندما يتم تجاوز وقت المعالج المخصص للبرنامج ، يبدأ إجراء الخروج. في حالة الذاكرة ، نحصل مرة أخرى على قيم للحدود غير الصارمة والصلبة ، وبعد ذلك نقوم بتعيين الحد باستخدام طريقة setrlimit ، والتي نمر بها إلى حجم القيد ( size ) والقيمة التي تم الحصول عليها مسبقًا من الحد الصعب.

التحكم في ما يمكن استيراده من الوحدة وما لا يمكن


تحتوي بعض اللغات على آليات تصدير واضحة للغاية من وحدات من المتغيرات والأساليب والواجهات. على سبيل المثال ، لا يتم تصدير سوى الكيانات التي تبدأ أسماؤها بحرف كبير إلى Golang. في بيثون ، يتم تصدير كل شيء. ولكن فقط حتى يتم __all__ السمة __all__ :

 def foo(): pass def bar(): pass __all__ = ["bar"] 

في المثال أعلاه ، سيتم تصدير وظيفة bar فقط. وإذا تركت السمة __all__ فارغة ، فلن يتم تصدير أي شيء من الوحدة النمطية على الإطلاق. ستؤدي محاولة استيراد شيء ما من وحدة نمطية كهذه إلى حدوث خطأ AttributeError .

تبسيط إنشاء عوامل المقارنة


هناك العديد من مشغلي المقارنة. على سبيل المثال ، __lt__ ، __le__ ، __gt__ ، __ge__ . قليل من الناس سوف يعجبهم احتمال تنفيذها لفئة معينة. هل هناك أي طريقة لتبسيط هذه المهمة المملة؟ نعم ، يمكنك ذلك - بمساعدة functools.total_ordering الديكور functools.total_ordering :

 from functools import total_ordering @total_ordering class Number: def __init__(self, value):  self.value = value def __lt__(self, other):  return self.value < other.value def __eq__(self, other):  return self.value == other.value print(Number(20) > Number(3)) print(Number(1) < Number(5)) print(Number(15) >= Number(15)) print(Number(10) <= Number(2)) 

functools.total_ordering استخدام functools.total_ordering decorator هنا لتبسيط عملية تطبيق ترتيب مثيلات الفصل. لضمان تشغيلها ، من الضروري فقط الإعلان عن مشغلي المقارنة __lt__ و __eq__ . هذا هو الحد الأدنى الذي يحتاجه الديكور لإنشاء عوامل المقارنة المتبقية.

النتائج


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

أعزائي القراء! هل تعرف أي ميزات بيثون القياسية التي قد تبدو غير عادية للوهلة الأولى ليتم تسميتها "قياسي"؟


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


All Articles