כדי לקבל מ-AI הסבר שימושי לקוד, אמרו כמה אתם כבר יודעים, בקשו את ההסבר שורה אחרי שורה, ובקשו מעקב: טבלה של הערכים שכל משתנה מחזיק בזמן שהקוד רץ. "הסבר את הקוד הזה" ריק מקבל סיכום שנכתב לקורא ממוצע דמיוני, ובדרך כלל הוא בסיסי מדי או מהיר מדי בשבילכם.
שורה אחרי שורה, עם מעקב אחרי ערכים
שתי הלשוניות שואלות על אותה פונקציה קצרה. השוו מה כל תשובה מאפשרת לכם לבדוק.
def running_max(nums):
result = []
best = None
for n in nums:
if best is None or n > best:
best = n
result.append(best)
return result
print(running_max([3, 1, 4, 1, 5]))הפונקציה הזו מחשבת את המקסימום המצטבר של רשימה. היא עוברת על המספרים, שומרת ב-best את הערך הגדול ביותר שנראה עד כה, ומוסיפה את הערך הזה ל-result בכל שלב. הבדיקה best is None מטפלת באיבר הראשון. הקריאה מדפיסה [3, 3, 4, 4, 5].
הפונקציה רצה בזמן O(n), כי היא עוברת על כל איבר פעם אחת.
התשובה הראשונה מדויקת, והיא עוזרת רק אם אתם כבר יודעים מה זה מקסימום מצטבר. היא גם מוסיפה הערה על סיבוכיות זמן שאף אחד לא ביקש, סוג התוספת שמקבלים כשהמודל לא יודע מי קורא. התשובה השנייה קושרת כל משפט לשורה שאפשר להצביע עליה, והטבלה הופכת לקונקרטי את מה שהסיכום רק מזכיר בחטף: result.append(best) רץ בכל סבב, כולל הסבבים שבהם best לא משתנה. בגלל זה 3 מופיע פעמיים, ואתם רואים את זה בשורה 2 במקום להסיק את זה מ-"בכל שלב".
טבלת מעקב היא גם בדיקה של ההסבר עצמו. אפשר לאמת כל שורה על ידי הרצת הקוד עם print(n, best, result) בתוך הלולאה. אם שורה לא מתאימה לפלט האמיתי, ההסבר שגוי איפשהו, ועכשיו אתם יודעים איפה.
הסבר ברמה שלכם
השורה השימושית ביותר בפרומפט הסבר היא מה שאתם כבר יודעים. היא אומרת למודל על אילו שורות לדלג ובאילו להאט. גם משפט תפקיד יכול לעזור ("אתה מורה פרטי לאנשים בחודש הראשון שלהם בתכנות"), אבל הוא עובד באותו מנגנון: הוא אומר למודל מי הקורא. Role prompting מסביר מה תפקיד משנה ומה לא.
הבלוק הזה הוא גרסה לשימוש חוזר. שנו את הרמה, את החלק המבלבל או את הקוד, וההסבר משתנה יחד איתם.
text = "the cat and the hat"
counts = {}
for word in text.split():
counts[word] = counts.get(word, 0) + 1
top = sorted(counts.items(), key=lambda kv: kv[1], reverse=True)[:2]
print(top)הלולאה סופרת כל מילה: counts מסתיים כ-{'the': 2, 'cat': 1, 'and': 1, 'hat': 1}.
עכשיו שתי השורות האחרונות, מבפנים החוצה:
counts.items()נותן את הזוגות('the', 2),('cat', 1),('and', 1),('hat', 1).lambda kv: kv[1]היא פונקציה זעירה בלי שם. היא מקבלת זוג אחד ומחזירה את האיבר השני שלו, הספירה. עבור('the', 2)היא מחזירה2.sorted(..., key=...)ממיינת את הזוגות לפי מה שהפונקציה הזו מחזירה, כלומר היא ממיינת לפי ספירה.reverse=Trueשם את הגדול ביותר ראשון. מילים עם ספירה שווה שומרות על הסדר המקורי שלהן.[:2]משאיר את שני הזוגות הראשונים.
אז top הוא [('the', 2), ('cat', 1)], וזה מה שמודפס.
"מילים עם ספירה שווה שומרות על הסדר המקורי שלהן" הוא הפרט שהסבר מהיר משמיט, והוא הסיבה ש-cat זוכה במקום השני ולא and או hat. ה-sorted של Python יציב, ו-reverse=True שומר על היציבות הזו. לא הייתם חושבים לשאול על זה, והבקשה ל-"ערך שכל חלק מפיק עבור הקלט הזה" היא מה שהעלה את זה לפני השטח.
לשאול על חלק אחד, לא על כל הקובץ
הדבקה של קובץ בן 500 שורות ושאלה "מה זה עושה" מקבלת סיור במבנה הקובץ. כשאתם תקועים על פונקציה אחת, הדביקו את הפונקציה הזו ואת השורות שקוראות לה, ושאלו עליה ישירות: "למה הפונקציה הזו חוזרת מוקדם כשהרשימה ריקה?" או "מה yield עושה בשורה 12, ומה היה משתנה אם זה היה return?" שאלה צרה מקבלת תשובה על הקוד שלכם; שאלה רחבה מקבלת תשובה על קוד שדומה לשלכם.
לבסיס קוד גדול ולא מוכר, הפכו את הסדר: בקשו קודם מפה ("פרט את המודולים העיקריים ומה כל אחד אחראי עליו, בשורה אחת לכל אחד"), ואז שאלו על המודול שאתם צריכים. זו שרשרת פרומפטים קטנה, וכל שלב שומר על תשובת המודל קצרה מספיק כדי לבדוק אותה.
הסבר דרך שפה שאתם מכירים
קוד בשפה לא מוכרת קל יותר לקריאה כשההסבר מעוגן בשפה שאתם מכירים. אמרו את זה בפרומפט: "אני מכיר Python. הסבר את פונקציית ה-Go הזו והצבע על כל מקום שבו היא מתנהגת אחרת ממה שמתכנת Python היה מצפה." ההבדלים הם המקום שבו אי ההבנות גרות: חלוקה של מספרים שלמים, ערכי אפס במקום None, slice שחולק זיכרון עם המערך שממנו הוא נוצר. הסבר פשוט של קוד ה-Go היה מתאר את השורות האלה נכון ולעולם לא היה אומר לכם שהאינטואיציות שלכם לגביהן שגויות.
לבדוק שהבנתם
הסבר שקראתם והסכמתם איתו עדיין יכול להשאיר אתכם בלי יכולת לכתוב את הקוד בעצמכם. שני פרומפטים סוגרים את הפער הזה:
- לחזות קודם. לפני שמריצים את הקוד או מבקשים הסבר, כתבו מה אתם חושבים שהוא מדפיס. אחר כך בקשו מהמודל להסביר רק את השורות שבהן התחזית שלכם הייתה שגויה.
- להסביר בחזרה. כתבו הסבר משלכם ובקשו מהמודל להצביע על כל דבר שגוי או חסר, בלי לשכתב אותו.
def running_max(nums):
result = []
best = None
for n in nums:
if best is None or n > best:
best = n
result.append(best)
return result
שאל אותי 3 שאלות שבודקות אם אני באמת מבין אותו, אחת בכל פעם. כלול שאלה אחת שבה אני צריך לחזות את הפלט עבור קלט חדש. חכה לתשובה שלי לפני שאתה שואל את השאלה הבאה, ואמור לי אם התשובה שלי נכונה ולמה.שאלה 1 מתוך 3: מה running_max([2, 7, 5, 9]) מחזירה? פתרו את זה לפני שאתם מריצים.
אותה גישה עובדת כשתוכנית מתנהגת לא כמו שצריך, אבל אז אתם רוצים את הסיבה, לא שיעור: ראו פרומפטים לדיבוג. כשהקוד שמולכם נכתב על ידי AI, הסבר שורה אחרי שורה הוא דרך מהירה לבדוק אותו לפני שאתם שומרים אותו; פרומפטים לכתיבת קוד מפרט את שאר הבדיקות שכדאי להריץ.
שאלות נפוצות
איך מבקשים מ-ChatGPT או מ-Claude להסביר קוד?
הדביקו את הקוד ואמרו שלושה דברים: מה אתם כבר יודעים, איזה חלק מבלבל אתכם, ובאיזו צורה אתם רוצים את ההסבר. "הסבר כל שורה במשפט אחד, ואז הראה טבלה של המשתנים אחרי כל סבב של הלולאה" מקבל תשובה שימושית הרבה יותר מ-"הסבר את הקוד הזה".
מה זו טבלת מעקב?
טבלת מעקב (trace table) עוקבת אחרי תוכנית בזמן שהיא רצה: שורה אחת לכל שלב (לעיתים קרובות סבב אחד של לולאה), עמודה אחת לכל משתנה, והערך של כל משתנה בנקודה הזו. בקשה לטבלה כזו הופכת תיאור מופשט לערכים קונקרטיים שאפשר לבדוק מול הקוד. זה תיעוד כתוב של מה שדיבאגר מראה לכם כשאתם מתקדמים בתוכנית צעד אחרי צעד.
האם AI יכול להסביר קוד בשפה שאני לא מכיר?
כן, וזה אחד הדברים השימושיים ביותר לבקש. ציינו שפה שאתם כן מכירים ובקשו מהמודל להשוות: "אני מכיר Python; הסבר את קוד ה-Rust הזה והצבע על המקומות שבהם הוא מתנהג אחרת מ-Python." בדקו את הטענות על התנהגות השפה על ידי הרצת דוגמאות קטנות, כי הסברים יכולים לטעות בביטחון מלא בפרטים.
האם שימוש ב-AI להסבר קוד פוגע בלמידה?
זה תלוי במה שעושים אחר כך. לקרוא הסבר ולהמשיך הלאה מלמד מעט. לחזות את הפלט לפני שמריצים את הקוד, לבקש מהמודל לבחון אתכם, או להסביר את הקוד בחזרה ולשאול במה טעיתם, כל אלה גורמים לכם לחשוב, ושם הלמידה קורית.