• בלוג
  • שלוש טעויות שכבר לא תעשו ב Python אחרי שתוסיפו Type Hints

שלוש טעויות שכבר לא תעשו ב Python אחרי שתוסיפו Type Hints

09/09/2019

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

1. חישוב סכום ספרות

הקוד הבא לא מצליח לחשב את סכום הספרות במספר 920:

num = 920
sum_of_digits = 0

while num > 0:
    sum_of_digits += (num % 10)
    num = num / 10

print(sum_of_digits)

אני מקווה שאתם יודעים למה, אבל בכל מקרה mypy יודע. הנה מה שקורה כשאני נותן ל mypy לרוץ על הקוד:

$ python3 -m mypy a.py
a.py:6: error: Incompatible types in assignment (expression has type "float", variable has type "int")

ובאמת המעבר של num ממשתנה int למשתנה float הוא זה שגם מקלקל את החישוב. החליפו את החלוקה בחלוקת מספרים שלמים ותקבלו את סכום הספרות הנכון וגם mypy ירגע.

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

2. המרת גיל לחודשים

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

age_in_years = input('how old are you? (in years) ')
age_in_months = age_in_years * 12

print(f"Wow that's {age_in_months} months")

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

בכל מקרה עם קצת עזרה נוכל לספר ל mypy שאנחנו חושבים שהגיל אמור להיות מספר והוא ישמח לעזור בחזרה ולספר ששכחנו להמיר את הקלט. תחילה התוכנית עם ה Type Hint:

age_in_years : int = input('how old are you? (in years) ')
age_in_months = age_in_years * 12

print(f"Wow that's {age_in_months} months")

והפלט של mypy:

$ python3 -m mypy a.py
a.py:1: error: Incompatible types in assignment (expression has type "str", variable has type "int")

3. היפוך רשימה

הקוד הבא לא מדפיס את הרשימה one, two, three מהסוף להתחלה:

data = ['one', 'two', 'three']
reversed_data = data.reverse()

print(reversed_data)

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

from typing import List

data = ['one', 'two', 'three']
reversed_data :List[str] = data.reverse()

print(reversed_data)

ועכשיו אנחנו מקבלים:

$ python3 -m mypy a.py
a.py:4: error: "reverse" of "list" does not return a value

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

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