כיצד לייעל את סקריפטי Python שלך לביצועים טובים יותר

Kyzd Lyy L T Sqrypty Python Slk Lbyzw Ym Twbym Ywtr



אופטימיזציה של הסקריפטים של Python לביצועים טובים יותר כרוכה בזיהוי וטיפול בצווארי הבקבוק בקוד שלנו, מה שגורם לו לרוץ מהר יותר ויעילה יותר. Python היא שפת תכנות פופולרית וחזקה הנמצאת בשימוש באפליקציות רבות בימינו כולל ניתוח נתונים, פרויקטי ML (למידת מכונה), פיתוח אתרים ועוד רבים. אופטימיזציה של קוד Python היא אסטרטגיה לשיפור המהירות והיעילות של תוכנית המפתחים בעת ביצוע כל פעילות תוך שימוש בפחות שורות קוד, פחות זיכרון או משאבים נוספים. קוד גדול ולא יעיל עלול להאט את התוכנית, מה שעלול לגרום לשביעות רצון לקוחות לקויה ולהפסד כספי פוטנציאלי, או לצורך בעבודה נוספת לתיקון ופתרון בעיות.

זה הכרחי בזמן ביצוע משימה הדורשת עיבוד של מספר פעולות או נתונים. לכן, מעבר ושיפור של כמה בלוקי קוד ופונקציונליות לא יעילים יכולים להביא לתוצאות מדהימות כמו הבאות:

  1. שפר את ביצועי האפליקציה
  2. צור קוד קריא ומאורגן
  3. הפוך את ניטור השגיאות וניפוי הבאגים לפשוטים יותר
  4. שמרו על כוח חישוב ניכר וכן הלאה

צור פרופיל של הקוד שלך

לפני שנתחיל לבצע אופטימיזציה, חיוני לזהות את החלקים בקוד הפרויקט שמאטים אותו. הטכניקות ליצירת פרופילים ב-Python כוללות את cProfile ואת חבילות הפרופיל. השתמש בכלים כאלה כדי לאמוד את מהירות הביצוע של פונקציות ושורות קוד מסוימות. מודול cProfile מייצר דוח המפרט את משך הזמן שלוקח לכל פונקציית סקריפט לפעול. דוח זה יכול לעזור לנו למצוא פונקציות שפועלות לאט כדי שנוכל לשפר אותן.







קטע קוד:



יְבוּא cProfile כפי ש cP
def לחשב סכום ( inputNumber ) :
sum_of_input_numbers = 0
בזמן inputNumber > 0 :
sum_of_input_numbers + = inputNumber % 10
inputNumber // = 10
הדפס ( 'הסכום של כל הספרות במספר הקלט הוא: 'סכום_של_מספר_הקלט'' )
לַחֲזוֹר sum_of_input_numbers
def main_func ( ) :
cP. לָרוּץ ( 'calculateSum(9876543789)' )
אם __שֵׁם__ == '__רָאשִׁי__' :
main_func ( )

התוכנית מבצעת בסך הכל חמש קריאות לפונקציות כפי שניתן לראות בשורה הראשונה של הפלט. הפרטים של כל קריאת פונקציה מוצגים בשורות הבאות, כולל מספר הפעמים שהפונקציה הופעלה, משך הזמן הכולל בפונקציה, משך הזמן לקריאה, ומשך הזמן הכולל בפונקציה (כולל כל הפונקציות שהיא נקראת).



בנוסף, התוכנית מדפיסה דוח על מסך ההנחיה שמראה שהתוכנית משלימה את זמן הביצוע של כל המשימות שלה תוך 0.000 שניות. זה מראה כמה מהירה התוכנית.





בחר את מבנה הנתונים הנכון

מאפייני הביצועים תלויים במבנה הנתונים. בפרט, מילונים מהירים יותר לחיפושים מאשר רשימות לגבי אחסון למטרות כלליות. בחר את מבנה הנתונים המתאים ביותר לפעולות שאנו נערוך על הנתונים שלך אם אתה מכיר את אלה. הדוגמה הבאה חוקרת את היעילות של מבני נתונים שונים עבור תהליך זהה כדי לקבוע אם קיים אלמנט במבנה הנתונים.



אנו מעריכים את הזמן שלוקח לבדוק אם קיים אלמנט בכל מבנה נתונים - רשימה, קבוצה ומילון - ומשווים ביניהם.

OptimizeDataType.py:

יְבוּא פעם שאני כפי ש tt
יְבוּא אַקרַאִי כפי ש rndobj
# צור רשימה של מספרים שלמים
random_data_list = [ rndobj. רנדינט ( 1 , 10000 ) ל _ ב טווח ( 10000 ) ]
# צור סט מאותם נתונים
ערכת_נתונים_אקראית = מַעֲרֶכֶת ( random_data_list )

# צור מילון עם אותם נתונים כמו מפתחות
obj_DataDictionary = { על אחד: אף אחד ל על אחד ב random_data_list }

# רכיב לחיפוש (קיים בנתונים)
מספר_אקראי_למצוא = rndobj. בְּחִירָה ( random_data_list )

# מדוד את הזמן לבדיקת חברות ברשימה
list_time = tt. פעם שאני ( למבדה : מספר_אקראי_למצוא ב random_data_list , מספר = 1000 )

# מדוד את הזמן לבדיקת חברות בסט
זמן מוגדר = tt. פעם שאני ( למבדה : מספר_אקראי_למצוא ב ערכת_נתונים_אקראית , מספר = 1000 )

# מדוד את הזמן לבדיקת חברות במילון
dict_time = tt. פעם שאני ( למבדה : מספר_אקראי_למצוא ב obj_DataDictionary , מספר = 1000 )

הדפס ( ו 'זמן בדיקת חברות ברשימה: {list_time:.6f} שניות' )
הדפס ( ו 'הגדר זמן בדיקת חברות: {set_time:.6f} שניות' )
הדפס ( ו 'זמן בדיקת חברות במילון: {dict_time:.6f} שניות' )

קוד זה משווה את הביצועים של רשימות, סטים ומילונים בעת בדיקת חברות. באופן כללי, סטים ומילון מהירים יותר באופן משמעותי מרשימות עבור מבחני חברות, מכיוון שהם משתמשים בחיפושים מבוססי-hash, כך שיש להם מורכבות זמן ממוצעת של O(1). רשימות, לעומת זאת, חייבות לבצע חיפושים ליניאריים שגורמים למבחני חברות עם מורכבות זמן O(n).

  צילום מסך של מחשב תיאור שנוצר באופן אוטומטי

השתמש בפונקציות המובנות במקום בלולאות

ניתן להשתמש במספר רב של פונקציות או שיטות מובנות ב- Python לביצוע משימות טיפוסיות כמו סינון, מיון ומיפוי. שימוש בשגרה אלה במקום יצירת לולאות מסייע להאיץ את הקוד מכיוון שלעתים קרובות הם מותאמים לביצועים.

בואו נבנה קוד לדוגמה כדי להשוות את הביצועים של יצירת לולאות מותאמות אישית על ידי שימוש בפונקציות המובנות עבור עבודות טיפוסיות (כגון map(), filter() ו- sorted()). אנו נעריך את ביצועי שיטות המיפוי, הסינון והמיון השונות.

BuiltInFunctions.py:

יְבוּא פעם שאני כפי ש tt
# רשימה לדוגמה של מספרים_רשימת
מספרים_רשימת = רשימה ( טווח ( 1 , 10000 ) )

# פונקציה לריבוע numbers_list באמצעות לולאה
def square_using_loop ( מספרים_רשימת ) :
תוצאה_מרובעת = [ ]
ל על אחד ב מספרים_רשימת:
תוצאה_מרובעת. לְצַרֵף ( על אחד ** 2 )
לַחֲזוֹר תוצאה_מרובעת
# פונקציה לסינון מספרים_רשימת זוגיים באמצעות לולאה
def filter_even_using_loop ( מספרים_רשימת ) :
filter_result = [ ]
ל על אחד ב מספרים_רשימת:
אם על אחד % 2 == 0 :
filter_result. לְצַרֵף ( על אחד )
לַחֲזוֹר filter_result
# פונקציה למיין numbers_list באמצעות לולאה
def sort_using_loop ( מספרים_רשימת ) :
לַחֲזוֹר מְמוּיָן ( מספרים_רשימת )
# למדוד את הזמן ל- square numbers_list באמצעות map()
map_time = tt. פעם שאני ( למבדה : רשימה ( מַפָּה ( למבדה x: x ** 2 , מספרים_רשימת ) ) , מספר = 1000 )
# מדוד את הזמן לסינון מספרים_רשימת זוגיים באמצעות filter()
filter_time = tt. פעם שאני ( למבדה : רשימה ( לְסַנֵן ( למבדה x: x % 2 == 0 , מספרים_רשימת ) ) , מספר = 1000 )
# למדוד את הזמן למיון numbers_list באמצעות sorted()
מיון_זמן = tt. פעם שאני ( למבדה : מְמוּיָן ( מספרים_רשימת ) , מספר = 1000 )
# מדוד את הזמן עד לריבוע numbers_list באמצעות לולאה
loop_map_time = tt. פעם שאני ( למבדה : square_using_loop ( מספרים_רשימת ) , מספר = 1000 )
# מדוד את הזמן לסינון מספרים_רשימת זוגיים באמצעות לולאה
loop_filter_time = tt. פעם שאני ( למבדה : filter_even_using_loop ( מספרים_רשימת ) , מספר = 1000 )
# מדוד את הזמן למיון numbers_list באמצעות לולאה
לולאה_מוין_זמן = tt. פעם שאני ( למבדה : sort_using_loop ( מספרים_רשימת ) , מספר = 1000 )
הדפס ( 'רשימת המספרים מכילה 10000 אלמנטים' )
הדפס ( ו 'Map() זמן: {map_time:.6f} שניות' )
הדפס ( ו 'Filter() זמן: {filter_time:.6f} שניות' )
הדפס ( ו 'Sorted() זמן: {sorted_time:.6f} שניות' )
הדפס ( ו 'זמן לולאה (מפה): {loop_map_time:.6f} שניות' )
הדפס ( ו 'זמן לולאה (מסנן): {loop_filter_time:.6f} שניות' )
הדפס ( ו 'זמן לולאה (ממוין): {loop_sorted_time:.6f} שניות' )

סביר להניח שנבחין שהפונקציות המובנות (map(), filter() ו- sorted()) מהירות יותר מהלולאות המותאמות אישית עבור המשימות הנפוצות הללו. הפונקציות המובנות ב- Python מציעות גישה תמציתית ומובנת יותר לביצוע משימות אלו והן מותאמות מאוד לביצועים.

בצע אופטימיזציה של הלולאות

אם יש צורך בכתיבת לולאות, יש כמה טכניקות שאנחנו יכולים לעשות כדי להאיץ אותן. בדרך כלל, לולאת range() מהירה יותר מאשר איטרציה לאחור. הסיבה לכך היא ש-range() יוצר איטרטור מבלי להפוך את הרשימה, מה שיכול להיות פעולה יקרה עבור רשימות ארוכות. בנוסף, מכיוון ש-range() אינו בונה רשימה חדשה בזיכרון, הוא משתמש בפחות זיכרון.

OptimizeLoop.py:

יְבוּא פעם שאני כפי ש tt
# רשימה לדוגמה של מספרים_רשימת
מספרים_רשימת = רשימה ( טווח ( 1 , 100000 ) )
# פונקציה לחזור על הרשימה בסדר הפוך
def loop_reverse_iteration ( ) :
תוצאה_הפוך = [ ]
ל י ב טווח ( רק ( מספרים_רשימת ) - 1 , - 1 , - 1 ) :
תוצאה_הפוך. לְצַרֵף ( מספרים_רשימת [ י ] )
לַחֲזוֹר תוצאה_הפוך
# פונקציה לחזור על הרשימה באמצעות range()
def איטרציה_טווח_לולאה ( ) :
טווח_תוצאות = [ ]
ל ק ב טווח ( רק ( מספרים_רשימת ) ) :
טווח_תוצאות. לְצַרֵף ( מספרים_רשימת [ ק ] )
לַחֲזוֹר טווח_תוצאות
# מדוד את הזמן שלוקח לביצוע איטרציה הפוכה
הפוך_זמן = tt. פעם שאני ( loop_reverse_iteration , מספר = 1000 )
# מדוד את הזמן שלוקח לבצע איטרציה של טווח
טווח_זמן = tt. פעם שאני ( איטרציה_טווח_לולאה , מספר = 1000 )
הדפס ( 'רשימת המספרים מכילה 100000 רשומות' )
הדפס ( ו 'זמן איטרציה הפוך: {reverse_time:.6f} שניות' )
הדפס ( ו 'זמן איטרציה של טווח: {range_time:.6f} שניות' )

הימנע משיחות פונקציה מיותרות

יש תקורה מסוימת בכל פעם שפונקציה נקראת. הקוד פועל מהר יותר אם נמנעים קריאות פונקציה מיותרות. לדוגמה, במקום לבצע שוב ושוב פונקציה שמחשבת ערך, נסה לאחסן את תוצאת החישוב במשתנה ולהשתמש בה.

כלים ליצירת פרופילים

כדי ללמוד עוד על ביצועי הקוד שלך, בנוסף לפרופיל מובנה, אנו יכולים להשתמש בחבילות הפרופיל החיצוניות כמו cProfile, Pyflame או SnakeViz.

תוצאות מטמון

אם הקוד שלנו צריך לבצע חישובים יקרים, אולי נשקול לשמור את התוצאות במטמון כדי לחסוך זמן.

Refactoring של קוד

שחזור הקוד כדי להקל על הקריאה והתחזוקה הוא לפעמים חלק הכרחי באופטימיזציה שלו. תוכנית מהירה יותר עשויה להיות גם נקייה יותר.

השתמש ב-Just-in-Time Compilation (JIT)

ספריות כמו PyPy או Numba יכולות לספק קומפילציה של JIT שיכולה להאיץ באופן משמעותי סוגים מסוימים של קוד Python.

שדרג את פייתון

ודא שאתה משתמש בגרסה העדכנית ביותר של Python מכיוון שגרסאות חדשות יותר כוללות לעתים קרובות שיפורים בביצועים.

מקביליות ומקבילות

עבור תהליכים שניתן לבצע במקביל, חקור את טכניקות המקבילות והסנכרון כמו ריבוי עיבוד, השרשור או אסינציו.

זכור ש-benchmarking ופרופיל צריך להיות המניעים העיקריים של אופטימיזציה. התרכז בשיפור תחומי הקוד שלנו שיש להם את ההשפעות המשמעותיות ביותר על הביצועים, ובדוק כל הזמן את השיפורים שלך כדי לוודא שיש להם את ההשפעות הרצויות מבלי להכניס עוד פגמים.

סיכום

לסיכום, אופטימיזציה של קוד Python היא חיונית לשיפור הביצועים ויעילות המשאבים. מפתחים יכולים להגביר מאוד את מהירות הביצוע וההיענות של יישומי Python שלהם באמצעות טכניקות שונות כגון בחירת מבני הנתונים המתאימים, מינוף הפונקציות המובנות, צמצום הלולאות הנוספות וניהול יעיל של הזיכרון. השוואת ביצועים ופרופילים מתמשכים צריכים לכוון את מאמצי האופטימיזציה, ולהבטיח שקידום הקוד תואם את דרישות הביצועים בעולם האמיתי. כדי להבטיח הצלחה ארוכת טווח של פרויקט ולהוריד את הסיכוי להחדרת בעיות חדשות, אופטימיזציה של הקוד צריכה להיות מאוזנת כל הזמן עם המטרות של קריאת קוד ותחזוקה.