كيفية تحسين نصوص بايثون الخاصة بك للحصول على أداء أفضل

Kyfyt Thsyn Nsws Baythwn Alkhast Bk Llhswl Ly Ada Afdl



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

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

  1. تعزيز أداء التطبيق
  2. إنشاء كود قابل للقراءة ومنظم
  3. اجعل مراقبة الأخطاء وتصحيح الأخطاء أسهل
  4. الحفاظ على قوة حسابية كبيرة وما إلى ذلك

قم بتعريف الكود الخاص بك

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







مقتطف الكود:



يستورد cProfile مثل سي بي
مواطنه com.calculateSum ( رقم الإدخال ) :
sum_of_input_numbers = 0
بينما رقم الإدخال > 0 :
sum_of_input_numbers + = رقم الإدخال % 10
رقم الإدخال // = 10
مطبعة ( 'مجموع كافة الأرقام في رقم الإدخال هو: 'sum_of_input_numbers'' )
يعود sum_of_input_numbers
مواطنه main_func ( ) :
سي بي. يجري ( 'حساب المجموع(9876543789)' )
لو __اسم__ == '__رئيسي__' :
main_func ( )

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



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





اختر بنية البيانات الصحيحة

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



نقوم بتقييم الوقت المستغرق للتحقق من وجود عنصر في كل بنية بيانات - قائمة ومجموعة وقاموس - ومقارنتها.

OptimizeDataType.py:

يستورد تيمي مثل تي تي
يستورد عشوائي مثل rndobj
# إنشاء قائمة الأعداد الصحيحة
Random_data_list = [ rndobj. randint ( 1 , 10000 ) ل _ في يتراوح ( 10000 ) ]
# إنشاء مجموعة من نفس البيانات
Random_data_set = تعيين ( Random_data_list )

# قم بإنشاء قاموس بنفس البيانات الموجودة في المفاتيح
obj_DataDictionary = { على واحد: لا أحد ل على واحد في Random_data_list }

# العنصر المطلوب البحث عنه (موجود في البيانات)
Random_number_to_find = rndobj. خيار ( Random_data_list )

# قياس الوقت للتحقق من العضوية في القائمة
list_time = تي تي. تيمي ( لامدا : رقم عشوائي_للبحث في Random_data_list , رقم = 1000 )

# قياس الوقت للتحقق من العضوية في المجموعة
ضبط الوقت = تي تي. تيمي ( لامدا : رقم عشوائي_للبحث في Random_data_set , رقم = 1000 )

# قياس الوقت للتحقق من العضوية في القاموس
dict_time = تي تي. تيمي ( لامدا : رقم عشوائي_للبحث في obj_DataDictionary , رقم = 1000 )

مطبعة ( F 'وقت التحقق من عضوية القائمة: {list_time:.6f} ثانية' )
مطبعة ( F 'تعيين وقت التحقق من العضوية: {set_time:.6f} ثانية' )
مطبعة ( F 'وقت التحقق من عضوية القاموس: {dict_time:.6f} ثانية' )

يقارن هذا الرمز أداء القوائم والمجموعات والقواميس عند إجراء عمليات التحقق من العضوية. بشكل عام، تكون المجموعات والقواميس أسرع بكثير من قوائم اختبارات العضوية لأنها تستخدم عمليات البحث المستندة إلى التجزئة، لذا فهي تتمتع بمتوسط ​​تعقيد زمني يبلغ O(1). من ناحية أخرى، يجب على القوائم إجراء عمليات بحث خطية تؤدي إلى اختبارات العضوية ذات التعقيد الزمني O(n).

  لقطة شاشة لجهاز الكمبيوتر تم إنشاء الوصف تلقائيًا

استخدم الوظائف المضمنة بدلاً من الحلقات

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

دعونا نبني بعض نماذج التعليمات البرمجية لمقارنة أداء إنشاء حلقات مخصصة من خلال استخدام الوظائف المضمنة للوظائف النموذجية (مثل الخريطة ()، والتصفية ()، والفرز (). سنقوم بتقييم مدى جودة أداء طرق التعيين والترشيح والفرز المختلفة.

بنيتInFunctions.py:

يستورد تيمي مثل تي تي
# قائمة عينة من Numbers_list
Numbers_list = قائمة ( يتراوح ( 1 , 10000 ) )

# دالة على قائمة الأرقام المربعة باستخدام حلقة
مواطنه Square_using_loop ( Numbers_list ) :
Square_result = [ ]
ل على واحد في قائمة الأرقام:
Square_result. ألحق ( على واحد ** 2 )
يعود Square_result
# وظيفة لتصفية قائمة الأرقام الزوجية باستخدام حلقة
مواطنه filter_even_using_loop ( Numbers_list ) :
filter_result = [ ]
ل على واحد في قائمة الأرقام:
لو على واحد ٪ 2 == 0 :
filter_result. ألحق ( على واحد )
يعود filter_result
# وظيفة لفرز قائمة الأرقام باستخدام حلقة
مواطنه Sort_using_loop ( Numbers_list ) :
يعود مرتبة ( Numbers_list )
# قم بقياس الوقت لتربيع قائمة الأرقام باستخدام الخريطة ()
Map_time = تي تي. تيمي ( لامدا : قائمة ( خريطة ( لامدا س: س ** 2 , Numbers_list ) ) , رقم = 1000 )
# قم بقياس الوقت لتصفية قائمة الأرقام الزوجية باستخدام عامل التصفية ()
filter_time = تي تي. تيمي ( لامدا : قائمة ( منقي ( لامدا س: س % 2 == 0 , Numbers_list ) ) , رقم = 1000 )
# قياس الوقت لفرز Numbers_list باستخدامsorted()
Sorted_time = تي تي. تيمي ( لامدا : مرتبة ( Numbers_list ) , رقم = 1000 )
# قم بقياس الوقت اللازم لتربيع قائمة الأرقام باستخدام حلقة
loop_map_time = تي تي. تيمي ( لامدا : Square_using_loop ( Numbers_list ) , رقم = 1000 )
# قم بقياس الوقت لتصفية قائمة الأرقام الزوجية باستخدام حلقة
loop_filter_time = تي تي. تيمي ( لامدا : filter_even_using_loop ( Numbers_list ) , رقم = 1000 )
# قياس الوقت لفرز Numbers_list باستخدام حلقة
حلقة_فرز_الوقت = تي تي. تيمي ( لامدا :sort_using_loop ( Numbers_list ) , رقم = 1000 )
مطبعة ( 'قائمة الأرقام تحتوي على 10000 عنصر' )
مطبعة ( F 'وقت الخريطة(): {map_time:.6f} ثانية' )
مطبعة ( F 'وقت التصفية(): {filter_time:.6f} ثانية' )
مطبعة ( F 'الوقت المصنف (): {sorted_time:.6f} ثانية' )
مطبعة ( F 'وقت الحلقة (الخريطة): {loop_map_time:.6f} ثانية' )
مطبعة ( F 'وقت الحلقة (الفلتر): {loop_filter_time:.6f} ثانية' )
مطبعة ( F 'وقت الحلقة (المرتبة): {loop_sorted_time:.6f} ثانية' )

من المحتمل أن نلاحظ أن الوظائف المضمنة (map()، وfilter()، وsorted()) أسرع من الحلقات المخصصة لهذه المهام الشائعة. توفر الوظائف المضمنة في Python طريقة أكثر إيجازًا ومفهومة لتنفيذ هذه المهام وهي مُحسّنة للغاية للأداء.

تحسين الحلقات

إذا كانت كتابة الحلقات ضرورية، فهناك بعض التقنيات التي يمكننا القيام بها لتسريعها. بشكل عام، تكون حلقة range() أسرع من التكرار للخلف. وذلك لأن النطاق () ينشئ مكررًا دون قلب القائمة، مما قد يكون عملية مكلفة للقوائم الطويلة. بالإضافة إلى ذلك، نظرًا لأن النطاق () لا ينشئ قائمة جديدة في الذاكرة، فإنه يستخدم ذاكرة أقل.

أوبتيميزلوب.بي:

يستورد تيمي مثل تي تي
# قائمة عينة من Numbers_list
Numbers_list = قائمة ( يتراوح ( 1 , 100000 ) )
# وظيفة للتكرار على القائمة بترتيب عكسي
مواطنه loop_reverse_iteration ( ) :
result_reverse = [ ]
ل ي في يتراوح ( فقط ( Numbers_list ) - 1 , - 1 , - 1 ) :
result_reverse. ألحق ( Numbers_list [ ي ] )
يعود result_reverse
# وظيفة للتكرار عبر القائمة باستخدام النطاق ()
مواطنه loop_range_iteration ( ) :
result_range = [ ]
ل ك في يتراوح ( فقط ( Numbers_list ) ) :
result_range. ألحق ( Numbers_list [ ك ] )
يعود result_range
# قياس الوقت المستغرق لإجراء التكرار العكسي
reverse_time = تي تي. تيمي ( loop_reverse_iteration , رقم = 1000 )
# قياس الوقت المستغرق لتكرار النطاق
range_time = تي تي. تيمي ( loop_range_iteration , رقم = 1000 )
مطبعة ( 'قائمة الأرقام تحتوي على 100000 سجل' )
مطبعة ( F 'وقت التكرار العكسي: {reverse_time:.6f} ثانية' )
مطبعة ( F 'وقت تكرار النطاق: {range_time:.6f} ثانية' )

تجنب استدعاءات الوظائف غير الضرورية

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

أدوات التنميط

لمعرفة المزيد حول أداء التعليمات البرمجية الخاصة بك، بالإضافة إلى ملفات التعريف المضمنة، يمكننا الاستفادة من حزم ملفات التعريف الخارجية مثل cProfile أو Pyflame أو SnakeViz.

نتائج ذاكرة التخزين المؤقت

إذا كان برنامجنا يحتاج إلى إجراء عمليات حسابية باهظة الثمن، فقد نفكر في تخزين النتائج مؤقتًا لتوفير الوقت.

إعادة هيكلة الكود

تعد إعادة هيكلة الكود لتسهيل قراءته وصيانته جزءًا ضروريًا في بعض الأحيان لتحسينه. قد يكون البرنامج الأسرع أيضًا أكثر نظافة.

استخدم التجميع في الوقت المناسب (JIT)

يمكن لمكتبات مثل PyPy أو Numba توفير تجميع JIT الذي يمكنه تسريع أنواع معينة من أكواد Python بشكل كبير.

ترقية بايثون

تأكد من أنك تستخدم أحدث إصدار من Python نظرًا لأن الإصدارات الأحدث غالبًا ما تتضمن تحسينات في الأداء.

التوازي والتزامن

بالنسبة للعمليات التي يمكن موازنتها، تحقق من تقنيات التوازي والمزامنة مثل المعالجة المتعددة أو الترابط أو عدم التزامن.

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

خاتمة

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