ושוב mypy הציל לי את היום
שימו לב לקוד הבא בלי Type Hints:
items = [{'a': 10, 'b': 20, '_id': 1},
{'a': 12, 'b': 31, '_id': 2}]
x = 5 # type: int
def print_item(items, index):
i = items[index]
del(i['_id'])
print(i)
print_item(items, 0)
print_item(items, 1)
רואים את הבאג? הקוד מדפיס את שני המילונים אבל מקלקל את הרשימה. אם נדפיס את items בסוף התוכנית נקבל:
[{'a': 10, 'b': 20}, {'a': 12, 'b': 31}]
כלומר מאפיין _id
נמחק. ברור שזו לא היתה הכוונה בכתיבת הפונקציה. print_item
רק צריכה להדפיס פריט בלי השדות המיוחדים שמתחילים בסימן קו תחתי, אבל על הדרך מישהו התבלבל ומחק מידע מרשימה שהתקבלה בתור קלט.
עכשיו אותו הקוד עם Type Hints:
from typing import Mapping
Items = list[Mapping[str, int]]
items: Items = [{'a': 10, 'b': 20, '_id': 1},
{'a': 12, 'b': 31, '_id': 2}]
x = 5 # type: int
def print_item(items: Items, index: int):
i = items[index]
del(i['_id'])
print(i)
print_item(items, 0)
print_item(items, 1)
print(items)
הפעם כבר בתוך PyCharm ובטח בהפעלת mypy מקבלים את השגיאה:
demo.py:12: error: "Mapping[str, int]" has no attribute "__delitem__"; maybe "__getitem__"? [attr-defined]
Found 1 error in 1 file (checked 1 source file)
נכון, צריך לזכור להשתמש בטיפוס הנכון (Mapping במקום dict לדברים שאתם לא רוצים שישתנו), וברור שהיה נחמד אם בדיקות כאלה היו קורות בברירת מחדל, ובכל זאת גם זו תזכורת טובה לחשיבות של Type Hints.