חוברת הקורס
הכל בעמוד אחד, להדפסה
כל התוכן בעמוד אחד. כפתור ההדפסה למטה שומר כ-PDF, וכל פרק מתחיל בעמוד חדש.
יחידה 2 — משתנים
מפת היחידה
| פרק | דקה | מה קורה שם |
|---|---|---|
| 2.1 | 0:55 | מה זה משתנה, והשמה עם = |
| 2.1 | 1:40 | משתנה הוא מצביע, לא קופסה |
| 2.1 | 2:22 | הטיפוסים str, int, float |
| 2.1 | 4:31 | לכתוב טוב: לא להחליף טיפוס של משתנה |
| 2.1 | 5:35 | חישוב ממשתנים אחרים |
| 2.2 | 0:21 | הטיפוס הבוליאני |
| 2.2 | 1:08 | ביטוי לוגי כערך |
| 2.2 | 2:41 | ==, !=, not, and, or |
| 2.2 | 4:43 | לכתוב טוב: רווחים וסוגריים בביטוי ארוך |
| 2.2 | 5:56 | האופרטור in |
| 2.2 | 6:23 | help(), ואיך יוצאים ממנו |
| 2.3 | 0:44 | קלט מהמשתמש עם input |
| 2.3 | 2:43 | TypeError: הקלט הוא תמיד מחרוזת |
| 2.3 | 3:17 | הסבה בין טיפוסים |
| 2.3 | 4:09 | החלפת ערכים בשורה אחת |
| 2.4 | 0:33 | קונבנציות כתיבה ו-PEP 8 |
| 2.4 | 2:20 | פייתון רגישה לגודל אות |
| 2.4 | 2:57 | אותיות קטנות, קו תחתון, וקבועים |
| 2.4 | 3:59 | שמות משמעותיים |
2.1 · משתנה הוא מצביע
משתנה הוא שם שמצביע על ערך. כותבים את השם, סימן שווה, ואת הערך:
>>> course = "Python"
>>> unit_name = 'variables'
>>> unit_number = 2
>>> chapter_length = 7.25
>>> course
'Python'
כדי לראות ערך של משתנה באינטרפרטר, מקלידים את השם ולוחצים Enter.
מה קורה בזיכרון. course = "Python" יוצר קודם אובייקט שמכיל את
הטקסט, ורק אחר כך משתנה בשם course שמצביע עליו. זו ההבחנה שהפרק חוזר
עליה פעמיים: המשתנה אינו הערך. הוא מצביע אליו.
ארבעה טיפוסים
כל אובייקט בפייתון הוא מטיפוס מסוים:
| ערך | טיפוס | מה זה |
|---|---|---|
"Python", 'variables' |
str |
מחרוזת. מרכאות כפולות או יחידות, שתיהן תקינות |
2 |
int |
מספר שלם |
7.25, 7.0 |
float |
מספר עשרוני. גם 7.0 הוא float |
True, False |
bool |
בוליאני. מגיע בפרק 2.2 |
לא מצהירים על הטיפוס. פייתון מזהה אותו לבד מהערך, וזה מה שנקרא dynamically typed.
שינוי ערך
"לשנות" משתנה זה להעביר אותו להצביע על אובייקט אחר:
>>> chapter_length = 7.25
>>> chapter_length = "7.25 minutes"
>>> chapter_length
'7.25 minutes'
לכתוב טוב: הדוגמה הזו עובדת, אבל היא bad practice. המשתנה התחיל כ-
floatועבר להצביע עלstr. פעולה שמתאימה לטיפוס אחד לא בהכרח מתאימה לשני, וכך נוצרות שגיאות שקשה למצוא. משתנה נשאר באותו טיפוס.
חישוב ממשתנים
>>> current_unit = unit_number
>>> next_unit = current_unit + 1
>>> next_unit
3
>>> print(current_unit - 1)
1
אחרי current_unit = unit_number שני המשתנים מצביעים על אותו
אובייקט, 2. ההדפסה בסוף היא כמה יחידות כבר הסתיימו: היחידה הנוכחית
עוד לא נגמרה, ולכן מפחיתים אחת.
2.2 · בוליאני וביטויים לוגיים
לטיפוס bool יש שני ערכים בלבד: True ו-False. שימו לב לאות
הגדולה, true בלי אות גדולה הוא שגיאה.
>>> i_am_hungry = True
ביטוי לוגי כערך
במקום לכתוב True או False ישירות, אפשר להשים תוצאה של ביטוי:
>>> number_of_sandwiches = 2
>>> i_am_hungry = number_of_sandwiches < 4
>>> i_am_hungry
True
כל מספר שאינו אפס נחשב True, ואפס הוא תמיד False. זה ייראה
שימושי כשיגיעו הלולאות.
>>> bool(5)
True
>>> bool(0)
False
האופרטורים
>>> number_of_sandwiches == 5
False
>>> number_of_sandwiches != 5
True
>>> not number_of_sandwiches != 5
False
== הוא השוואה, ו-= הוא השמה. מי שמבלבל ביניהם יבלבל עוד הרבה
פעמים, ולכן כדאי לעצור על זה עכשיו.
and דורש ששני הצדדים יהיו נכונים, ו-or מסתפק באחד:
>>> cups_of_coffee = 3
>>> number_of_sandwiches < 4 and cups_of_coffee > 5
False
>>> number_of_sandwiches < 4 or cups_of_coffee > 5
True
לכתוב טוב: ביטוי ארוך
ביטוי שבנוי משלושה תנאים: רעב אם אכלתי לפחות כריך אחד וגם פחות מארבעה, או בדיוק שתי קערות מרק. שני שינויים הופכים אותו לקריא: רווח משני צדי כל אופרטור, וסוגריים סביב כל תנאי.
>>> bowls_of_soup = 0
>>> i_am_hungry = (((number_of_sandwiches >= 1)
... and (number_of_sandwiches < 4))
... or (bowls_of_soup == 2))
>>> i_am_hungry
True
in
בודק אם מחרוזת אחת נמצאת בתוך אחרת:
>>> "break" in "breakfast"
True
>>> "b" in "food"
False
בקשת עזרה
אף אחד לא זוכר את כל הפקודות. מה שצריך לזכור הוא איפה מחפשים.
help()פותח את ספריית העזרה של פייתון. שם מקלידים, למשל,inומקבלים הסבר מלא.- רווח מדפדף, ו-
qיוצא. בלי זה אפשר להיתקע שם. help("in")הולך ישר לנושא, בלי להיכנס לממשק.- באינטרנט יש תיעוד רב, אבל רק לפייתון 3. זו הגרסה של הקורס, וחלק מההסברים ברשת עוד נכתבו לגרסה 2.
2.3 · קלט, הסבה והחלפה
input
input עוצר את התוכנית ומחכה שהמשתמש יקליד ויקיש Enter. מה שבסוגריים
מוצג לו על המסך:
name = input("What is your name? ")
print(name)
הקיצור _: באינטרפרטר, המשתנה _ מחזיק את התוצאה האחרונה. אם
הרצתם input(...) בלי לשמור, _ עדיין מכיל את מה שהוקלד. זה עובד רק
באינטרפרטר, לא בקובץ.
התקלה המרכזית של הפרק
>>> number = "5"
>>> print(number ** 2)
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'
בשורה הראשונה "5" במקום input(), כי זה בדיוק מה ש-input מחזיר:
input מחזיר תמיד מחרוזת, גם כשהוקלד מספר. ואי אפשר להעלות
מחרוזת בחזקה.
הסבה (casting)
כותבים את הטיפוס הרצוי, ובסוגריים את הערך:
>>> int(number) ** 2
25
>>> float(number)
5.0
החלפת ערכים בשורה אחת
>>> peter_pan_home = "Neverland"
>>> snow_white_home = "the forest"
>>> peter_pan_home, snow_white_home = snow_white_home, peter_pan_home
>>> peter_pan_home
'the forest'
>>> snow_white_home
'Neverland'
בשפות כמו C ו-Java החלפה דורשת משתנה זמני ושלוש שורות.
2.4 · שמות למשתנים
קונבנציות כתיבה הן מוסכמות של הקהילה על איך קוד נראה. פייתון לא אוכפת אותן, והקוד ירוץ גם בלעדיהן. המסמך שמרכז אותן הוא PEP 8, והקורס מצפה לעבוד לפיו.
פייתון רגישה לגודל אות
>>> nose_length = 4
>>> Nose_length = 6
>>> Nose_length - nose_length
2
אלה שני משתנים שונים (case-sensitive), והקוד תקין. אבל מי שקורא אותו לא יודע מה ההבדל ביניהם. כאן הקונבנציות נכנסות.
הכללים
| כלל | דוגמה |
|---|---|
| אותיות קטנות | character = "Pinocchio" |
| יותר ממילה אחת: קו תחתון ביניהן | nose_length |
| קבוע, ערך שלא משתנה בתוכנית: אותיות גדולות | PI = 3.14 |
| שם שאומר מה יש בו | fairy_tale_file_with_extension, ולא file |
קבוע הוא קונבנציה בלבד. אם משנים את PI באמצע התוכנית, פייתון לא
תזרוק שגיאה. האחריות על המתכנת.
שמות כלליים כמו number או name עובדים, אבל לא אומרים כלום. שם
ארוך ומפורט עדיף, כי הוא חוסך לקורא את הניחוש.
בדיקה עצמית
- אחרי
a = 5ואזb = a, על מה מצביעb? - מה הטיפוס של
"2" + "2", ומה הערך? - מה התוצאה של
not 0? - המשתמש הקליד
7ב-x = input(). מה יחזירx * 2? - איזה שם עדיף לפי PEP 8:
Total,total_priceאוtp?
תשובות.
1: על אותו אובייקט, 5. שני שמות, ערך אחד.
2: str, והערך '22'.
3: True, כי 0 נחשב False.
4: '77'. הקלט הוא מחרוזת, וכפל מחרוזת במספר משכפל אותה. כדי לקבל
14 צריך int(x) * 2.
5: total_price. אותיות קטנות, קו תחתון, ושם שאומר מה יש בו.
יחידה 3 — מחרוזות
מפת היחידה
| פרק | דקה | מה קורה שם |
|---|---|---|
| 3.1 | 0:23 | מה זו מחרוזת |
| 3.1 | 1:01 | השגיאה הראשונה: מרכאות שלא תואמות |
| 3.1 | 2:50 | גרש באמצע מחרוזת |
| 3.1 | 4:16 | הלוכסן ההפוך, \ |
| 3.1 | 4:47 | שרשור עם + והכפלה עם * |
| 3.1 | 5:26 | str() |
| 3.2 | 0:46 | \n ו-\t |
| 3.2 | 1:27 | נתיב קובץ שנשבר |
| 3.2 | 2:37 | מרכאות משולשות |
| 3.3 | 1:01 | אינדקסים, מאפס |
| 3.3 | 1:41 | אינדקס שלילי |
| 3.3 | 2:06 | IndexError |
| 3.3 | 2:52 | חיתוך (slicing) |
| 3.3 | 3:42 | להשמיט התחלה או סוף |
| 3.3 | 5:18 | חיתוך בקפיצות |
| 3.3 | 6:04 | מחרוזת לא ניתנת לשינוי |
| 3.4 | 0:58 | למה פונקציות |
| 3.4 | 1:48 | math.sqrt |
| 3.4 | 2:25 | פונקציה מול מתודה |
| 3.4 | 3:11 | upper ו-zfill |
| 3.4 | 4:40 | dir |
| 3.4 | 5:04 | לכתוב טוב: רווחים |
3.1 · יצירת מחרוזות
מחרוזת (str) היא רצף של תווים, אפילו תו אחד, בתוך מרכאות. המרכאות
אומרות לפייתון שזה טקסט, ולא שם של פקודה או של משתנה.
השגיאה הראשונה
>>> 'I really hope defining this string will work"
Traceback (most recent call last):
...
SyntaxError: unterminated string literal (detected at line 1)
איך קוראים את ההודעה. ה-Traceback אומר באיזו שורה פייתון נתקעה, סמן קטן מצביע על המקום, והשורה האחרונה אומרת מה סוג השגיאה.
כאן זו שגיאת תחביר, SyntaxError: הקוד לא בנוי לפי חוקי השפה.
המחרוזת נפתחה במרכאה יחידה, ופייתון הגיעה לסוף השורה בלי למצוא את
המרכאה הסוגרת.
בסרטון ההודעה מופיעה כ-EOL while scanning string literal, ניסוח של
גרסאות ישנות יותר. בגרסה עדכנית תופיע ההודעה שלמעלה. המשמעות זהה.
הכלל: כפולות או יחידות, שתיהן בסדר, כל עוד אותה מחרוזת נפתחת ונסגרת באותו סוג.
גרש באמצע
>>> 'What's wrong here?'
Traceback (most recent call last):
...
SyntaxError: unterminated string literal (detected at line 1)
פייתון קוראת את המחרוזת 'What', ונתקעת באות s שאחריה. ההודעה בסרטון
הייתה invalid syntax, ושוב, זה ניסוח של גרסה אחרת.
שלושה פתרונות:
>>> "What's wrong here?"
"What's wrong here?"
>>> 'She said "maybe" and left'
'She said "maybe" and left'
>>> print("She said \"don't\" twice")
She said "don't" twice
- גרש בפנים: עוטפים במרכאות כפולות
- מרכאות כפולות בפנים: עוטפים ביחידות
- גם וגם: לוכסן הפוך (
\, backslash) לפני התו הבעייתי. השם שלו הוא escape character, כי הוא "מבריח" את התו שאחריו מהמשמעות הרגילה שלו
שרשור והכפלה
>>> first = "We "
>>> second = "belong "
>>> third = "together"
>>> first + second + third
'We belong together'
>>> duplicate_me = ":) "
>>> duplicate_me * 8
':) :) :) :) :) :) :) :) '
הטיפ: רווח בסוף כל חלק. בלעדיו המילים נדבקות.
str()
>>> x = 3
>>> type(x)
<class 'int'>
>>> x + x
6
>>> x = str(x)
>>> type(x)
<class 'str'>
>>> x + x
'33'
אותו +, שתי תוצאות. על מספרים זה חיבור, ועל מחרוזות זה שרשור.
3.2 · תווים מיוחדים
| תו | מה עושה |
|---|---|
\n |
שורה חדשה |
\t |
הזחה (טאב) |
\\ |
לוכסן הפוך אחד, כמו שהוא |
טבלת תוצאות במחרוזת אחת
>>> rounds_and_winners = "Round\tWinner\n1\tA\n2\tB\n3\tA"
>>> print(rounds_and_winners)
Round Winner
1 A
2 B
3 A
שימו לב: רק print מציג את השורות והטאבים. בלי print האינטרפרטר
מראה את המחרוזת עם \n ו-\t כמו שהם.
כשזה מפריע: נתיב של קובץ
>>> print("C:\tournaments\new_scores.txt")
C: ournaments
ew_scores.txt
פייתון ראתה \t ו-\n והדפיסה טאב ושורה חדשה. הפתרון: לוכסן הפוך
נוסף, שמנטרל את המיוחד:
>>> print("C:\\tournaments\\new_scores.txt")
C:\tournaments\new_scores.txt
מרכאות משולשות
שלוש מרכאות בהתחלה ושלוש בסוף. אפשר לשבור שורות ב-Enter, בלי \n,
ואפשר לכתוב גרש בפנים בלי בעיה:
>>> how_to_win = """Three steps to win at chess:
... Don't lose your queen
... Control the center
... Checkmate"""
>>> print(how_to_win)
Three steps to win at chess:
Don't lose your queen
Control the center
Checkmate
... הוא האינטרפרטר שמחכה להמשך. לא מקלידים אותו.
שימוש נוסף, שיגיע בהמשך הקורס: תיעוד של קוד, הסבר מפורט על מה שקטע קוד עושה.
3.3 · גישה למחרוזת
אינדקס
גישה לתו היא לפי המיקום שלו, ולא לפי הערך. סופרים מאפס, ומבקשים בסוגריים מרובעים:
>>> card_str = "joker"
>>> card_str[0]
'j'
>>> card_str[1]
'o'
| תו | j |
o |
k |
e |
r |
|---|---|---|---|---|---|
| מההתחלה | 0 | 1 | 2 | 3 | 4 |
| מהסוף | -5 | -4 | -3 | -2 | -1 |
>>> card_str[-1]
'r'
>>> card_str[-5]
'j'
מעבר לגבול
>>> card_str[5]
Traceback (most recent call last):
...
IndexError: string index out of range
ל-"joker" יש חמישה תווים, ולכן המיקום האחרון הוא 4. גם card_str[-6]
ייתן את אותה שגיאה. הטיפ: לבדוק את האורך לפני. איך, יגיע בהמשך.
חיתוך
[התחלה:סוף]. ההתחלה נכללת, הסוף לא:
>>> game = "gaming"
>>> game[0:2]
'ga'
>>> game[2:5]
'min'
סוף פחות התחלה הוא אורך המקטע. 5 - 2 הם שלושה תווים.
להשמיט: בלי התחלה, פייתון מתחילה מ-0. בלי סוף, היא ממשיכה עד הסוף. בלי שניהם, מתקבלת כל המחרוזת:
>>> game[:2]
'ga'
>>> game[2:]
'ming'
>>> game[:]
'gaming'
>>> game[:-1]
'gamin'
[:-1] הוא הכל חוץ מהתו האחרון.
בקפיצות
נקודתיים שלישיות, וגודל הקפיצה:
>>> game[0:5:2]
'gmn'
>>> game[1::2]
'aig'
כך מקבלים את כל המיקומים הזוגיים, או האי-זוגיים, בלי לולאה.
אי אפשר לשנות מחרוזת
>>> my_string = "Change me"
>>> my_string[0] = "S"
Traceback (most recent call last):
...
TypeError: 'str' object does not support item assignment
מחרוזת היא immutable, לא ניתנת לשינוי. המונח הזה יחזור.
מה כן עושים: יוצרים מחרוזת חדשה עם השינוי, ומעבירים את המשתנה להצביע עליה:
>>> my_string = "S" + my_string[1:]
>>> my_string
'Shange me'
זה בדיוק מה שקורה בכל "שינוי" של משתנה מחרוזת: ההצבעה עוברת למחרוזת חדשה, והישנה לא נגעה.
3.4 · פונקציות ומתודות
למה בכלל. ביטוי שיש בו חמישה שורשים ריבועיים פירושו לכתוב חמש פעמים את הקוד שמחשב שורש. ואם יש בו טעות, מתקנים חמש פעמים. פונקציה נכתבת פעם אחת, ונקראת כמה פעמים שצריך.
פונקציה
שם, סוגריים, ובתוכם הפרמטרים, מופרדים בפסיקים:
>>> import math
>>> math.sqrt(9)
3.0
>>> math.sqrt(16) + math.sqrt(25)
9.0
import math טוען את הספרייה, ואז math.sqrt קורא לפונקציה מתוכה.
שימו לב שהתוצאה היא 3.0 ולא 3: sqrt מחזירה תמיד float.
פונקציות משלכם מגיעות ביחידה 5.
מתודה
פונקציה ששייכת לטיפוס מסוים. קודם האובייקט, אחר כך נקודה, השם וסוגריים:
>>> "print me in upper case".upper()
'PRINT ME IN UPPER CASE'
>>> "1".zfill(5)
'00001'
>>> "234".zfill(5)
'00234'
upperבלי פרמטרים. הסוגריים נכתבים בכל זאת, ריקיםzfill(רוחב)מרפדת באפסים משמאל עד הרוחב שביקשתם
הנקודה מטעה. ב-math.sqrt היא אומרת "מתוך הספרייה". ב-"1".zfill
היא אומרת "המתודה של האובייקט הזה". ומאחורי הקלעים, האובייקט עצמו
נשלח למתודה בתור הפרמטר הראשון.
איך מוצאים מתודות
dir(str)
מחזיר רשימה ארוכה של כל מה שאפשר לעשות עם מחרוזת. upper ו-zfill
נמצאות בסוף.
לכתוב טוב: רווחים
| כלל | נכון | לא |
|---|---|---|
| רווח אחד אחרי כל פסיק | f(a, b, c) |
f(a,b,c) |
| פרמטר אחד: בלי רווחים בכלל | f(a) |
f( a ) |
| רווח משני צדי אופרטור | x = 1 + 2 |
x=1+2 |
בדיקה עצמית
- מה ההבדל בין
print("a\tb")לבין הקלדת"a\tb"באינטרפרטר? - עם
s = "python": מה זהs[-3:]? - מה זה
s[::-1]? (לא הופיע בסרטון. נסו לנחש לפי הכלל.) - איך הופכים את
"cat"ל-"bat"? - מה ההבדל בין
math.sqrt(x)לביןx.upper()?
תשובות.
1: print מציג טאב אמיתי. האינטרפרטר מציג את המחרוזת כמו שהיא, עם
\t.
2: 'hon'.
3: 'nohtyp'. קפיצה שלילית עוברת על המחרוזת מהסוף להתחלה.
4: "b" + "cat"[1:]. אי אפשר לשנות תו בתוך מחרוזת, אז בונים חדשה.
5: sqrt היא פונקציה מתוך הספרייה math. upper היא מתודה של
מחרוזות, והאובייקט שלפני הנקודה הוא מה שהיא פועלת עליו.
יחידה 4 — תנאים
מפת היחידה
| פרק | דקה | מה קורה שם |
|---|---|---|
| 4.0 | 0:00 | אינטרפרטר מול עורך טקסט |
| 4.0 | 0:34 | קובץ .py והרצה |
| 4.1 | 0:00 | מה זה בלוק |
| 4.1 | 0:31 | שורת פקודה ונקודתיים |
| 4.1 | 1:03 | הזחה: ארבעה רווחים |
| 4.1 | 1:34 | IndentationError |
| 4.1 | 2:43 | pass |
| 4.2 | 0:32 | if ובקרת זרימה |
| 4.2 | 1:36 | else |
| 4.2 | 1:57 | elif |
| 4.2 | 3:07 | למה לא תנאי בתוך תנאי |
| 4.2 | 3:30 | תנאי עם and |
4.0 · עורך טקסט
עד עכשיו הקוד נכתב באינטרפרטר. זה טוב לשורה אחת ולבדיקה מהירה, אבל
תוכנית של עשרות שורות כותבים בעורך טקסט ושומרים כקובץ עם הסיומת
.py.
| אינטרפרטר | עורך טקסט | |
|---|---|---|
| למה | שורות קצרות, ניסוי | תוכנית שלמה |
| נשמר | לא | קובץ .py |
| פלט | מיד אחרי כל שורה | אחרי הרצה של כל הקובץ |
ערך בלי print |
מוצג | לא מוצג |
השורה האחרונה בטבלה היא ההבדל שתופס הכי הרבה אנשים: באינטרפרטר
"hi".upper() מציג 'HI'. בקובץ, בלי print, לא יוצג כלום.
כל עורך עובד, גם פנקס רשימות. עורך מתאים לתכנות צובע את הקוד, משלים שמות ומסמן טעויות. ההרצה תלויה בעורך. בקורס זה כפתור run.
מכאן והלאה הדוגמאות בקורס מגיעות בשתי הצורות: קצרות באינטרפרטר, וארוכות בעורך.
4.1 · בלוקים
בלוק הוא קבוצת שורות ששייכות לאותו רצף לוגי. שני חוקים:
- השורה הראשונה מסתיימת בנקודתיים. זו שורת הפקודה, כמו
if. - השורות של הבלוק מוזחות ביחס אליה. הקורס, כמו PEP 8, משתמש בארבעה רווחים.
>>> finished_chapter = True
>>> learners = 10
>>> if finished_chapter:
... print("Well done!")
... learners = learners + 1
...
Well done!
>>> learners
11
שתי השורות המוזחות רצות רק אם התנאי נכון. ההזחה היא מה שאומר לפייתון איפה הבלוק נגמר. בשפות אחרות עושים את זה בסוגריים מסולסלים. בפייתון זה הרווחים.
הזחה היא תחביר
>>> debugging = "oops"
>>> print(debugging)
Traceback (most recent call last):
...
IndentationError: unexpected indent
רווחים בתחילת שורה שלא אמורה להיות מוזחת הם שגיאה, ולא עניין של סגנון. ולא מערבבים רווחים וטאבים באותו קובץ.
pass
בלוק לא יכול להיות ריק. כשכותבים שלד של תוכנית ועוד לא יודעים מה ייכנס
לבלוק, כותבים pass, והתוכנית רצה:
>>> grade = 75
>>> if grade > 90:
... print("Good job")
... else:
... pass # TODO: what to say below 90
...
ההערה שאחרי # היא תזכורת לעצמכם. פייתון מתעלמת ממנה.
4.2 · if, else, elif
תנאי מאפשר להחליט אילו שורות ירוצו. זה נקרא בקרת זרימה.
>>> weather = "sunny"
>>> if weather == "rainy":
... print("Take an umbrella")
... elif weather == "sunny":
... print("Take a hat and sunglasses")
... else:
... print("Take a light jacket")
...
Take a hat and sunglasses
| מתי רץ | חובה? | |
|---|---|---|
if |
התנאי נכון | כן, תמיד ראשון |
elif |
כל מה שלפניו לא התקיים, והתנאי שלו כן | לא. כמה שרוצים |
else |
שום דבר לפניו לא התקיים | לא. רק אחד, ותמיד אחרון |
פייתון בודקת לפי הסדר ועוצרת בראשון שמתקיים. אם גם if וגם elif
נכונים, רק הבלוק של if ירוץ.
בחירה של המשתמש
choice = input("Pick a number: ")
if choice == "1":
print("You chose 1")
elif choice == "2":
print("You chose 2")
elif choice == "3":
print("You chose 3")
else:
print("You chose another number")
שימו לב ל-"1" במרכאות: input מחזיר מחרוזת, כמו ביחידה 2. השוואה
ל-1 בלי מרכאות לא תתקיים אף פעם.
למה elif ולא תנאי בתוך תנאי
אותה תוכנית בלי elif דורשת if בתוך else בתוך else, וכל רמה
מוזחת עוד ארבעה רווחים. זה נקרא קינון (nesting), והקורס מגדיר אותו
כמסורבל. elif שומר את כל האפשרויות באותה רמה.
תנאי מורכב
כל מה שלמדנו על and ו-or ביחידה 2 עובד גם כאן:
>>> months_since_last_eclipse = 18
>>> moon_position = 42
>>> sun_position = 42
>>> if ((months_since_last_eclipse == 18)
... and (moon_position == sun_position)):
... print("Solar eclipse!")
... else:
... print("Just a regular day")
...
Solar eclipse!
מלכודת שהסרטון רק מזכיר: משתנה שמקבל ערך רק בתוך אחד הבלוקים לא
קיים אם הבלוק הזה לא רץ. ניסיון להשתמש בו אחר כך נותן NameError.
הפתרון הפשוט: לתת לו ערך לפני התנאי.
בדיקה עצמית
x = 5. בתנאי הראשוןx > 3מדפיסA, וב-elif x > 1מדפיסB. מה יודפס?- מה חסר כאן:
if x > 3 print("big")? - אפשר לכתוב
elseבליifלפניו? - למה
if input() == 5:לא יתקיים אף פעם?
תשובות.
1: רק A. פייתון עוצרת בתנאי הראשון שמתקיים, גם אם x > 1 נכון.
2: נקודתיים אחרי התנאי, ושורה חדשה מוזחת.
3: לא. else ו-elif באים תמיד אחרי if.
4: input מחזיר מחרוזת, ו-"5" אינו שווה ל-5.
יחידה 5 — פונקציות
מפת היחידה
| פרק | דקה | מה קורה שם |
|---|---|---|
| 5.1 | 0:00 | למה פונקציות |
| 5.1 | 1:05 | def, וקריאה לפונקציה |
| 5.1 | 1:39 | פונקציה עם פרמטר |
| 5.1 | 2:42 | שם בלי סוגריים: פונקציה היא אובייקט |
| 5.1 | 3:45 | פרמטר מול ארגומנט |
| 5.1 | 4:16 | ארגומנט מהטיפוס הלא נכון |
| 5.2 | 0:32 | משתנה בתוך פונקציה ומחוצה לה |
| 5.2 | 1:05 | טווח הכרה: גלובלי ולוקאלי |
| 5.2 | 2:11 | NameError מחוץ לפונקציה |
| 5.2 | 3:14 | אותו שם בפנים ובחוץ |
| 5.2 | 5:21 | קריאת משתנה גלובלי, ולמה לא |
| 5.2 | 5:53 | global |
| 5.3 | 0:35 | return |
| 5.3 | 2:10 | פונקציה בלי return מחזירה None |
| 5.3 | 3:16 | החזרת כמה ערכים |
| 5.3 | 4:20 | ערכי ברירת מחדל |
| 5.3 | 6:23 | ברירת מחדל רק בסוף |
| 5.3 | 7:25 | ארגומנטים לפי שם |
| 5.4 | 1:05 | תיעוד (docstring) |
| 5.4 | 3:21 | help ו-__doc__ |
| 5.4 | 4:24 | הפונקציה main |
| 5.4 | 6:35 | קוד לא קריא מול קוד קריא |
| 5.4 | 8:17 | ארבעה כללים לפונקציות |
5.1 · לכתוב פונקציה
פונקציה היא רצף פקודות באותו בלוק, שמבצע משימה מוגדרת. כותבים אותה פעם אחת, נותנים לה שם, וקוראים לה כמה פעמים שצריך. קל יותר לשנות, לבדוק ולדבג. ביחידה 3 השתמשנו בפונקציות מוכנות. מכאן כותבים לבד.
>>> def my_first_function():
... print("This is my first function in Python")
...
>>> my_first_function()
This is my first function in Python
def(מ-define), שם הפונקציה, סוגריים ונקודתיים- גוף הפונקציה מוזח, כמו כל בלוק
- הגדרה אינה הרצה. הפונקציה רצה רק כשקוראים לה, עם סוגריים
פרמטר
>>> def square(number):
... print(number ** 2)
...
>>> square(3)
9
פונקציה עם פרמטר מצפה לקבל אותו בכל קריאה. בלעדיו:
>>> square()
Traceback (most recent call last):
...
TypeError: square() missing 1 required positional argument: 'number'
פרמטר מול ארגומנט
| מה זה | בדוגמה | |
|---|---|---|
| פרמטר | השם בהגדרה | number |
| ארגומנט | הערך שנשלח בקריאה | 3 |
שם בלי סוגריים
>>> square
<function square at 0x...>
אין שגיאה, ושום דבר לא רץ. שם של פונקציה בלי סוגריים הוא כמו שם של
משתנה: הוא מצביע על אובייקט, והאובייקט הוא הפונקציה עצמה. (המספר אחרי
at הוא המיקום בזיכרון, ומשתנה בכל הרצה.)
ולכן אפשר להשים פונקציה למשתנה:
>>> func = square
>>> func(6)
36
הטיפוס של הארגומנט
>>> square("3")
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'
פייתון לא בודקת טיפוסים מראש. השגיאה תופיע רק כשהשורה תרוץ, ויכולה להפיל את התוכנית באמצע. שליחת הטיפוס הנכון היא באחריות מי שקורא לפונקציה, ואת הטיפוס המצופה מוצאים בתיעוד שלה (פרק 5.4).
5.2 · טווח הכרה
טווח הכרה (scope) הוא האזור בתוכנית שבו משתנה קיים.
| איפה הוגדר | איפה מוכר | |
|---|---|---|
| גלובלי | בתוכנית, מחוץ לכל פונקציה | בכל התוכנית |
| לוקאלי | בתוך פונקציה | רק בתוך הפונקציה |
>>> fish_num = 9
>>> def fish_food():
... food_for_fish = 5
... print(food_for_fish * fish_num)
...
>>> fish_food()
45
fish_num גלובלי, ו-food_for_fish לוקאלי. כמו דגים: הם קיימים רק
באקווריום.
לוקאלי מחוץ לפונקציה
>>> def ocean():
... fish_view = "coral reef"
... print(fish_view)
...
>>> ocean()
coral reef
>>> print(fish_view)
Traceback (most recent call last):
...
NameError: name 'fish_view' is not defined
אותו שם בפנים ובחוץ
>>> animal = "rabbit"
>>> def water():
... animal = "goldfish"
... print(animal)
...
>>> water()
goldfish
>>> print(animal)
rabbit
ההשמה בתוך הפונקציה יצרה משתנה לוקאלי חדש, ולא שינתה את הגלובלי. כשיש שני משתנים באותו שם, הלוקאלי קודם: פייתון מחפשת קודם בתוך הפונקציה, ורק אם לא מצאה עוברת לגלובלי.
הפתרון: שמות שונים. land_animal ו-sea_animal, וכבר לא צריך
לנחש.
לקרוא משתנה גלובלי מתוך פונקציה
זה עובד (ראינו את fish_num למעלה), אבל לא מומלץ, אלא אם זה קבוע.
הדרך המסודרת להכניס ערך לפונקציה היא כארגומנט.
global
>>> animal = "rabbit"
>>> def water():
... global animal
... animal = "goldfish"
... print(animal)
...
>>> water()
goldfish
>>> print(animal)
goldfish
global אומר לפייתון שהשם הוא של המשתנה הגלובלי, ולכן ההשמה משנה אותו.
אפשרי, וממש לא מומלץ: פונקציה שמשנה משתנים מבחוץ קשה לבדוק ולהבין.
5.3 · קלט ופלט של פונקציה
return
print מציג ערך ושוכח אותו. return מחזיר אותו, ואפשר להמשיך
לעבוד איתו.
>>> def num_of_oranges(small_cups, large_cups):
... return small_cups + large_cups * 3
...
>>> oranges = num_of_oranges(8, 10)
>>> oranges
38
כוס קטנה היא תפוז אחד, וגדולה היא שלושה. oranges מצביע על הערך
שהוחזר, 38, ולא על הפונקציה.
בלי return: None
>>> def greet_customers(small_cups, large_cups):
... total = small_cups + large_cups
... print("Thanks for ordering", total, "cups!")
...
>>> result = greet_customers(2, 1)
Thanks for ordering 3 cups!
>>> print(result)
None
כל פונקציה מחזירה משהו. בלי return, היא מחזירה את None, אובייקט
שמשמעותו "כלום". return None ו-return לבד מחזירים את אותו דבר.
כמה ערכים
>>> def amount_of_oranges(small_cups, large_cups):
... oranges = small_cups + large_cups * 3
... kilograms = oranges / 5
... return oranges, kilograms
...
>>> oranges_number, kilograms_to_buy = amount_of_oranges(15, 5)
>>> oranges_number
30
>>> kilograms_to_buy
6.0
מפרידים בפסיקים ב-return, ומקבלים לתוך כמה משתנים, כמו בהחלפת ערכים
ביחידה 2. מאחורי הקלעים חוזר tuple, שמגיע ביחידה 8.
ערכי ברירת מחדל
>>> def amount_of_oranges(small_cups=20, large_cups=10):
... oranges = small_cups + large_cups * 3
... return oranges, oranges / 5
...
>>> amount_of_oranges()
(50, 10.0)
>>> amount_of_oranges(3, 4)
(15, 3.0)
ארגומנט עם ברירת מחדל נקרא גם אופציונלי: אפשר לשלוח אותו, ולא חובה.
ברירת מחדל רק בסוף:
>>> def amount_of_oranges(small_cups=20, large_cups):
... pass
Traceback (most recent call last):
...
SyntaxError: parameter without a default follows parameter with a default
אם היה מותר, amount_of_oranges(5) היה דו-משמעי: האם 5 הולך לראשון
או לשני? לכן פרמטרים עם ברירת מחדל באים אחרי כל אלה שבלי.
ארגומנטים לפי שם
>>> def profit(small_cups, large_cups,
... small_price, large_price):
... print(small_cups * small_price
... + large_cups * large_price)
...
>>> profit(large_price=10, small_price=4,
... large_cups=3, small_cups=5)
50
כשכותבים את שם הפרמטר, הסדר לא משנה, והקריאה מסבירה את עצמה. נוח במיוחד כשיש הרבה פרמטרים. אבל כל פרמטר בלי ברירת מחדל חייב לקבל ערך:
>>> profit(large_cups=3, small_price=4, large_price=10)
Traceback (most recent call last):
...
TypeError: profit() missing 1 required positional argument: 'small_cups'
5.4 · תיעוד, main וקונבנציות
docstring
תיעוד אומר מה הפונקציה עושה ואיך משתמשים בה. גם קוד שכתבתם בעצמכם נהיה לא מובן אחרי כמה שבועות. כותבים אותו מיד אחרי שורת ההגדרה, במרכאות משולשות:
>>> import math
>>> def num_of_bottles(total_liters):
... """Calculates how many 1.5 L bottles to take.
... :param total_liters: total water needed
... :type total_liters: float
... :return: the number of bottles
... :rtype: int
... """
... return math.ceil(total_liters / 1.5)
...
>>> num_of_bottles(4)
3
| שורה | מה כותבים |
|---|---|
| ראשונה | מה הפונקציה עושה, במשפט |
:param שם: |
מה הפרמטר. שורה לכל פרמטר |
:type שם: |
הטיפוס שלו |
:return: |
מה חוזר. בלי return: None |
:rtype: |
הטיפוס של מה שחוזר |
(math.ceil מעגלת כלפי מעלה, כי שני בקבוקים וחצי הם שלושה בקבוקים.
היא מאותה ספרייה של sqrt.)
לקרוא את התיעוד
>>> print(num_of_bottles.__doc__.splitlines()[0])
Calculates how many 1.5 L bottles to take.
help(num_of_bottles) מציג את כל התיעוד, ו-num_of_bottles.__doc__
מחזיר אותו כמחרוזת. שני קווים תחתונים מכל צד.
מעכשיו, תיעוד לכל פונקציה שאתם כותבים, כולל בפתרונות התרגילים.
main
תוכנית שרק מגדירה פונקציות לא מדפיסה כלום: פייתון מגדירה אותן, ומסיימת.
צריך לקרוא להן. בקורס עושים את זה מתוך פונקציה ראשית בשם main, במבנה
הזה:
def welcome_hikers():
print("Welcome to the trail!")
def remind_water():
print("Don't forget to drink water.")
def main():
welcome_hikers()
remind_water()
if __name__ == "__main__":
main()
mainהיא הראשונה שנקראת כשמריצים את הקובץ, והיא קוראת לכל השאר- שורת ה-
ifהמוזרה נראית מסתורית עכשיו. היא תהיה הגיונית כשתכתבו ספריות משלכם. בינתיים: הקורס מבקש לכתוב לפי המבנה הזה מעכשיו - השם
mainהוא קונבנציה, לא חוק. ובכל זאת,main - שתי שורות ריקות בין פונקציות. כך ממליץ PEP 8, ולכן גם בדוגמה
קוד קריא
הסרטון מראה תוכנית שבה המשתנים נקראים c, t, ts, ואי אפשר להבין
מה היא עושה. אותה תוכנית בדיוק, עם שמות ברורים ותיעוד, מתגלה כתחזית
מזג אוויר לעיר שהמשתמש מקליד. ההבדל הוא רק בשמות.
ארבעה כללים
- מטרה אחת לכל פונקציה. פונקציה ממוקדת אפשר להשתמש בה בהרבה מקומות
- שם שאומר מה היא עושה, ותיעוד שתואם לו
- קלט ופלט ברורים
- שורה ריקה בין פונקציות (שתיים, לפי PEP 8)
בדיקה עצמית
- מה ההבדל בין
print(x)לביןreturn xבתוך פונקציה? - מה יודפס?
def f(): x = 1ואזf()ואזprint(x). - מה מחזירה פונקציה שאין בה
return? - האם מותר
def g(a, b=2, c):? - במה
squareשונה מ-square()?
תשובות.
1: print מציג ושוכח. return מחזיר ערך שאפשר לשמור ולהמשיך איתו.
2: NameError. x לוקאלי, וקיים רק בתוך f.
3: None.
4: לא. אחרי פרמטר עם ברירת מחדל, גם c חייב לקבל ברירת מחדל.
5: square הוא הפונקציה עצמה, כאובייקט. square() מריץ אותה.
יחידה 6 — רשימות
מפת היחידה
| פרק | דקה | מה קורה שם |
|---|---|---|
| 6.1 | 0:30 | רשימה ריקה, ו-type |
| 6.1 | 1:00 | איברים מטיפוסים שונים, וגישה במיקום |
| 6.1 | 1:39 | רשימה בתוך רשימה |
| 6.1 | 3:18 | הפונקציה list |
| 6.2 | 0:00 | רשימה ומחרוזת הן רצפים |
| 6.2 | 1:01 | גישה וחיתוך |
| 6.2 | 2:05 | שרשור, ו-TypeError |
| 6.2 | 3:11 | הכפלה ו-len |
| 6.3 | 0:31 | רשימה ניתנת לשינוי |
| 6.3 | 1:02 | append ו-+= |
| 6.3 | 1:33 | שינוי איבר, ו-IndexError |
| 6.3 | 3:11 | remove, ו-ValueError |
| 6.3 | 3:42 | in |
| 6.3 | 4:46 | count ו-sort |
| 6.3 | 5:16 | sort מול sorted |
| 6.3 | 6:22 | מיון עם key |
6.1 · מהי רשימה
רשימה (list) מחזיקה כמה אובייקטים במקום אחד, ושומרת על הסדר שלהם.
סוגריים מרובעים, ופסיקים בין האיברים:
>>> movies = []
>>> type(movies)
<class 'list'>
>>> movies = ["Titanic", "Up", "Inception",
... "Coco", "Amelie"]
האיברים לא חייבים להיות מאותו טיפוס:
>>> titanic = [1997, "Leonardo DiCaprio",
... "Kate Winslet", 194, True]
>>> titanic[0]
1997
>>> titanic[1]
'Leonardo DiCaprio'
>>> titanic[3]
194
שנה, שני שחקנים, אורך בדקות, וצפיתי או לא. גישה היא לפי מיקום, מאפס, בדיוק כמו במחרוזת.
רשימה בתוך רשימה
איבר ברשימה יכול להיות רשימה. לאיבר הפנימי ניגשים עם זוג סוגריים נוסף:
>>> unique = [["a", "list"], ["of", "lists"]]
>>> unique[0]
['a', 'list']
>>> unique[0][1]
'list'
>>> unique[1][0]
'of'
הסוגריים הראשונים בוחרים רשימה פנימית, והשניים בוחרים איבר בתוכה. זה שימושי לטבלה: כל רשימה פנימית היא שורה, למשל אדם, שנת לידה ומקצוע.
list()
>>> empty_list = list()
>>> empty_list
[]
>>> list("Letters")
['L', 'e', 't', 't', 'e', 'r', 's']
list על מחרוזת מפרק אותה לתווים.
6.2 · רשימות ומחרוזות הן רצפים
רצף הוא אוסף של פריטים בסדר מסוים. מחרוזת היא רצף של תווים, ורשימה היא רצף של איברים. ולכן מה שלמדנו ביחידה 3 עובד גם כאן:
>>> my_subject = "chemistry"
>>> chemical_elements = ["hydrogen", "helium",
... "lithium", "beryllium"]
| פעולה | מחרוזת | רשימה |
|---|---|---|
| גישה | my_subject[3] הוא 'm' |
chemical_elements[3] הוא 'beryllium' |
| מהסוף | my_subject[-1] הוא 'y' |
chemical_elements[-1] הוא 'beryllium' |
| חיתוך | my_subject[1:3] הוא 'he' |
chemical_elements[1:3] הוא ['helium', 'lithium'] |
| אורך | len(my_subject) הוא 9 |
len(chemical_elements) הוא 4 |
>>> chemical_elements[1:3]
['helium', 'lithium']
>>> len(chemical_elements)
4
שרשור: רק רשימה לרשימה
>>> chemical_elements + "boron"
Traceback (most recent call last):
...
TypeError: can only concatenate list (not "str") to list
>>> chemical_elements + ["boron"]
['hydrogen', 'helium', 'lithium', 'beryllium', 'boron']
כמו שאי אפשר לשרשר מספר למחרוזת. העטיפה בסוגריים מרובעים הופכת את
"boron" לרשימה עם איבר אחד.
הכפלה
>>> ["H", "O"] * 3
['H', 'O', 'H', 'O', 'H', 'O']
6.3 · פעולות על רשימות
ההבדל הגדול ממחרוזת
מחרוזת היא immutable. רשימה היא mutable: אפשר להוסיף, לשנות ולמחוק אחרי שהיא נוצרה.
>>> solar_system = ["Mercury", "Venus", "Earth",
... "Mars", "Jupiter", "Saturn",
... "Uranus", "Neptune"]
>>> len(solar_system)
8
להוסיף
>>> solar_system.append("Novo")
>>> solar_system[-1]
'Novo'
>>> solar_system += ["Novo"]
>>> solar_system[-2:]
['Novo', 'Novo']
שתי דרכים: append לאיבר אחד, ו-+= עם רשימה (שיכולה להכיל כמה
איברים). שימו לב: append לא מחזירה כלום. היא משנה את הרשימה עצמה.
לשנות
>>> solar_system[8] = "De Novo"
>>> solar_system[9] = "Sun"
>>> solar_system[10] = "Sun"
Traceback (most recent call last):
...
IndexError: list assignment index out of range
משנים איבר במיקום שקיים. מיקום שלא קיים זו שגיאה, וכדי להוסיף בסוף
משתמשים ב-append.
למחוק
>>> solar_system.remove("De Novo")
>>> solar_system.remove("De Novo")
Traceback (most recent call last):
...
ValueError: list.remove(x): x not in list
removeמקבלת ערך, לא מיקום, ומוחקת רק את המופע הראשון שלו- ערך שלא קיים ברשימה:
ValueError
לכן בודקים לפני:
>>> "Earth" in solar_system
True
>>> "Pluto" in solar_system
False
עוד מתודות ופונקציות
(הטמפרטורות כאן לדוגמה בלבד.)
>>> temperature = [59, -180, 867, -180, 333]
>>> temperature.count(-180)
2
>>> max(temperature)
867
>>> sorted(temperature)
[-180, -180, 59, 333, 867]
>>> temperature
[59, -180, 867, -180, 333]
>>> temperature.sort()
>>> temperature
[-180, -180, 59, 333, 867]
| מה מחזיר | משנה את הרשימה? | |
|---|---|---|
sorted(lst) |
רשימה חדשה ממוינת | לא |
lst.sort() |
None |
כן |
זה ההבדל ממה שהכרנו במחרוזות: "abc".upper() מחזירה מחרוזת חדשה
ולא נוגעת במקורית. מתודות של רשימה כמו sort ו-append משנות את
הרשימה עצמה.
מיון עם key
>>> astro_objects = ["moon", "asteroid", "galaxy"]
>>> sorted(astro_objects)
['asteroid', 'galaxy', 'moon']
>>> sorted(astro_objects, key=len)
['moon', 'galaxy', 'asteroid']
key הוא פרמטר אופציונלי שמקבל פונקציה. היא רצה על כל איבר, והמיון
נעשה לפי מה שהיא החזירה. כאן len, ולכן לפי אורך. (שימו לב: len בלי
סוגריים. מעבירים את הפונקציה עצמה, כמו ביחידה 5.)
אפשר להעביר גם פונקציה שכתבתם. אילו פונקציות מקבלות key, ומה עוד הן
מקבלות, מוצאים בתיעוד של פייתון.
בדיקה עצמית
- עם
grid = [[1, 2], [3, 4]], מה זהgrid[1][0]? - מה ההבדל בין
lst.append([5])לביןlst += [5]? - מה יחזיר
x = [3, 1, 2].sort(), ועל מה מצביעx? - למה
"hi"[0] = "H"נכשל, ו-["h", "i"][0] = "H"לא? - איך ממיינים רשימת מילים מהארוכה לקצרה? (רמז:
help(sorted))
תשובות.
1: 3.
2: append([5]) מוסיף רשימה כאיבר אחד, [..., [5]]. += [5] מוסיף
את 5.
3: None. sort משנה את הרשימה ולא מחזירה אותה. צריך sorted.
4: מחרוזת היא immutable, ורשימה היא mutable.
5: sorted(words, key=len, reverse=True).
יחידה 7 — לולאות
מפת היחידה
| פרק | דקה | מה קורה שם |
|---|---|---|
| 7.1 | 0:31 | "כל עוד": הרעיון של while |
| 7.1 | 1:05 | איטרציה, ומתי הלולאה נעצרת |
| 7.1 | 1:36 | מונה מ-0 עד 4 |
| 7.1 | 2:10 | לולאה אינסופית |
| 7.1 | 2:40 | הקלט שלא נגמר: שגיאה לוגית |
| 7.1 | 4:49 | break ו-continue |
| 7.2 | 0:30 | שלוש פעמים אותו קוד |
| 7.2 | 1:32 | for |
| 7.2 | 2:34 | המשתנה אחרי הלולאה |
| 7.2 | 2:50 | for על מחרוזת, ועל רשימה של רשימות |
| 7.2 | 3:42 | אותו דבר ב-while וב-for |
| 7.2 | 4:14 | range |
7.1 · לולאת while
while חוזרת על בלוק כל עוד תנאי מתקיים. כמו דוב בתרדמת חורף:
כל עוד מזג האוויר חורפי, הוא ממשיך לישון. מספר הסבבים לא ידוע מראש.
>>> i = 0
>>> while i < 5:
... print(i)
... i += 1
...
0
1
2
3
4
- כל סבב נקרא איטרציה
- לפני כל איטרציה פייתון בודקת את התנאי.
False: הלולאה נגמרת.True: הבלוק רץ, וחוזרים לבדוק i += 1הוא קיצור שלi = i + 1. בלעדיוiנשאר 0, והלולאה לא נגמרת
לולאה אינסופית
while True:
handle_next_request()
לפעמים בכוונה: שרת שאמור לעבוד כל הזמן. הרבה יותר פעמים בטעות,
בגלל תנאי שלא יכול להפוך ל-False. מפסיקים תוכנית תקועה עם Ctrl+C.
הקלט שלא נגמר
התוכנית שואלת כמה חודשים בשנה דובי גריזלי ישנים, וממשיכה לשאול עד שעונים 5, 6 או 7:
user_input = input("Hibernation months? ")
while (user_input != 5 and user_input != 6
and user_input != 7):
print(user_input)
user_input = input("Try again: ")
עונים 7, ושוב נשאלים. עונים 5, ושוב. הלולאה לא נגמרת אף פעם, כי
input מחזיר מחרוזת, ו-"7" אף פעם לא שווה ל-7. התיקון:
user_input = int(input("Hibernation months? "))
while (user_input != 5 and user_input != 6
and user_input != 7):
print(user_input)
user_input = int(input("Try again: "))
זו שגיאה לוגית. אין הודעת שגיאה ואין קריסה. התוכנית פשוט עושה משהו אחר ממה שהתכוונתם. ולכן היא הכי קשה למצוא.
break ו-continue
| מה עושה | |
|---|---|
break |
יוצא מהלולאה מיד, בלי עוד איטרציות |
continue |
מדלג על שאר האיטרציה הנוכחית, וממשיך לבאה |
>>> i = 0
>>> while i < 10:
... i += 1
... if i % 2 == 0:
... break
... print(i)
...
1
% הוא שארית חלוקה. i % 2 == 0 פירושו "i זוגי". הלולאה הדפיסה
1, ועצרה כש-i הגיע ל-2.
>>> i = 0
>>> while i < 10:
... i += 1
... if i % 2 == 0:
... continue
... print(i)
...
1
3
5
7
9
אותו קוד עם continue: במספר זוגי ה-print מדולג, והלולאה ממשיכה.
7.2 · לולאת for
הבעיה
animals = ["bear", "husky", "reindeer"]
animal = animals[0]
print(animal)
animal = animals[1]
print(animal)
animal = animals[2]
print(animal)
אותן שתי שורות שלוש פעמים, ורק המיקום משתנה. "עבור כל חיה ברשימה, הדפס אותה" כתוב בפייתון כמעט באותן מילים:
>>> animals = ["bear", "husky", "reindeer"]
>>> for animal in animals:
... print(animal)
...
bear
husky
reindeer
for, שם משתנה, in, ורצף. in כאן הוא חלק מהלולאה, ולא הבדיקה
מיחידה 2: בכל איטרציה הוא משים ל-animal את האיבר הבא.
המשתנה נשאר
>>> animal
'reindeer'
אחרי הלולאה המשתנה עדיין קיים, ומצביע על האיבר האחרון.
על כל רצף
מחרוזת היא רצף, ולכן for עובר עליה תו אחרי תו:
>>> for letter in "bear":
... print(letter)
...
b
e
a
r
ורשימה של רשימות:
>>> animal_sounds = [["dog", "woof"],
... ["cat", "meow"],
... ["cow", "moo"]]
>>> for pair in animal_sounds:
... print(pair[0], pair[1])
...
dog woof
cat meow
cow moo
אותו דבר, שלוש דרכים
>>> num = 0
>>> while num < 5:
... print(num, end=" ")
... num += 1
...
0 1 2 3 4
>>> for num in [0, 1, 2, 3, 4]:
... print(num, end=" ")
...
0 1 2 3 4
>>> for num in range(5):
... print(num, end=" ")
...
0 1 2 3 4
(end=" " מדפיס רווח במקום שורה חדשה, כדי שהפלט ייכנס בשורה אחת.)
range
range מייצרת סדרת מספרים, בלי לכתוב רשימה:
| פירוש | מתקבל | |
|---|---|---|
range(5) |
מ-0 עד 5, בלי 5 | 0 1 2 3 4 |
range(5, 10) |
מ-5 עד 10 | 5 6 7 8 9 |
range(0, 10, 3) |
מ-0 עד 10, בקפיצות של 3 | 0 3 6 9 |
range(5, 0, -1) |
קפיצה שלילית | 5 4 3 2 1 |
>>> list(range(0, 10, 3))
[0, 3, 6, 9]
>>> list(range(5, 0, -1))
[5, 4, 3, 2, 1]
range(start, stop, step): start ברירת מחדל 0, step ברירת מחדל 1,
ו-stop לא נכלל. בדיוק כמו בחיתוך.
while או for
while |
for |
|
|---|---|---|
| מתי | לא יודעים מראש כמה פעמים | עוברים על רצף, או מספר פעמים ידוע |
| דוגמה | עד שהמשתמש יענה נכון | כל איבר ברשימה |
| סכנה | לולאה אינסופית | כמעט אין |
בדיקה עצמית
- מה ידפיס
for x in range(2, 8, 2): print(x)? - למה
while i < 5: print(i)(בלי שום שורה נוספת) לא נגמרת? - מה ההבדל בין
breakל-continue? - אחרי
for c in "abc": pass, על מה מצביעc? - איך מדפיסים את המספרים מ-10 עד 1?
תשובות.
1: 2, 4, 6. 8 לא נכלל.
2: i לא משתנה, ולכן התנאי נשאר True.
3: break יוצא מהלולאה. continue מדלג רק על האיטרציה הנוכחית.
4: 'c', האיבר האחרון.
5: for n in range(10, 0, -1): print(n).
יחידה 8 — טאפל ומילון
מפת היחידה
| פרק | דקה | מה קורה שם |
|---|---|---|
| 8.1 | 0:33 | טאפל ריק, וסוגריים עגולים |
| 8.1 | 1:05 | טאפל בלי סוגריים |
| 8.1 | 1:36 | טאפל עם איבר אחד: הפסיק |
| 8.1 | 2:38 | מה משותף לטאפל ולרשימה |
| 8.1 | 4:25 | טאפל לא ניתן לשינוי |
| 8.1 | 5:26 | למה בכלל טאפל |
| 8.1 | 6:32 | מתי טאפל ומתי רשימה |
| 8.2 | 0:30 | השמה לכמה משתנים בבת אחת |
| 8.2 | 2:10 | פונקציה שמחזירה כמה ערכים |
| 8.2 | 4:15 | תבנית מחרוזת עם % |
| 8.2 | 6:17 | %d, ולמה זה עדיף על + |
| 8.3 | 0:32 | מפתח וערך |
| 8.3 | 1:02 | {} ו-dict() |
| 8.3 | 2:40 | שליפה לפי מפתח |
| 8.3 | 3:14 | KeyError |
| 8.3 | 4:16 | הוספה ועדכון |
| 8.3 | 6:05 | del ו-pop |
| 8.3 | 6:38 | keys, values, items |
8.1 · טאפל
טאפל (tuple) מחזיק כמה איברים, גם מטיפוסים שונים, בדיוק כמו
רשימה. ההבדל: אחרי שנוצר, אי אפשר לשנות אותו.
>>> my_first_tuple = ()
>>> type(my_first_tuple)
<class 'tuple'>
>>> lunch = (3.5, 2, "sandwich")
>>> lunch = 3.5, 2, "sandwich"
>>> lunch
(3.5, 2, 'sandwich')
סוגריים עגולים, ופסיקים. ובלי סוגריים בכלל, פייתון אורזת את הערכים לטאפל לבד.
איבר אחד: הפסיק
>>> type((20))
<class 'int'>
>>> type((20,))
<class 'tuple'>
(20) הוא רק 20 בסוגריים, כמו בחשבון. הפסיק הוא מה שהופך את זה
לטאפל.
מה עובד כמו ברשימה
טאפל הוא רצף, ולכן גישה, חיתוך, len, in ולולאת for עובדים:
>>> lunch[0]
3.5
>>> lunch[1:]
(2, 'sandwich')
>>> len(lunch)
3
>>> for item in lunch:
... print(item)
...
3.5
2
sandwich
בסרטון רצות כאן עוד כמה פקודות על הטאפל, שמוצגות על המסך בלי הסבר בקול, ולכן הן לא בסיכום.
מה לא עובד
>>> salad = ("cucumber", "tomato", "tuna", "lemon")
>>> salad[2] = "spinach"
Traceback (most recent call last):
...
TypeError: 'tuple' object does not support item assignment
| רשימה | טאפל | מחרוזת | |
|---|---|---|---|
| סוגריים | [ ] |
( ) |
מרכאות |
| שינוי | mutable | immutable | immutable |
| הוספה ומחיקה | כן | לא | לא |
אז למה טאפל
- בטוח. מה שלא אמור להשתנות לא ישתנה בטעות
- חסכוני בזיכרון. לרשימה מוקצה מקום נוסף כדי שתוכל לגדול. לטאפל בדיוק כמה שצריך
מתי טאפל
כששני תנאים מתקיימים: מספר האיברים קבוע, ולמיקום יש משמעות. הדוגמה הקלאסית: נקודה בגרף. תמיד שני איברים, והראשון הוא x והשני y.
>>> point = (5, 2)
8.2 · שימושים בטאפל
השמה מרובה
>>> food, kind, calories = "bread", "whole wheat", 80
>>> food
'bread'
>>> calories
80
טאפל של שמות משמאל, טאפל של ערכים מימין, וכל שם מקבל את הערך שבמקום שלו. וזה מה שקרה בהחלפת הערכים ביחידה 2:
>>> my_basket, your_basket = "bread", "fruit"
>>> my_basket, your_basket = your_basket, my_basket
>>> my_basket
'fruit'
פונקציה שמחזירה כמה ערכים
ביחידה 5 ראינו return a, b. מה שחוזר הוא טאפל:
>>> def picnic_shopping(prices):
... total = sum(prices)
... return total, total <= 150
...
>>> result = picnic_shopping([12.5, 25, 60])
>>> type(result)
<class 'tuple'>
>>> money, is_budget_possible = picnic_shopping([12.5, 25, 60])
>>> money
97.5
>>> is_budget_possible
True
(sum מחברת את כל האיברים ברשימה.)
תבנית מחרוזת
שרשור עם + עובד, אבל ארוך ומבולגן, ונופל על מספרים:
>>> fruit = "grapes"
>>> cheese = "brie"
>>> print("In the basket: " + fruit + " and " + cheese)
In the basket: grapes and brie
>>> print("In the basket: %s and %s" % (fruit, cheese))
In the basket: grapes and brie
%s |
מקום לערך (s מ-string) |
%d |
מקום למספר שלם |
% (a, b) |
אחרי המחרוזת: טאפל של הערכים, לפי הסדר |
היתרון: הטקסט נפרד מהמשתנים, וקל לשנות כל אחד מהם. ואפשר לשבץ מספרים בלי הסבה:
>>> drivers = 1
>>> role = "designated driver"
>>> print("We need %d %s" % (drivers, role))
We need 1 designated driver
>>> print("We need " + drivers + " " + role)
Traceback (most recent call last):
...
TypeError: can only concatenate str (not "int") to str
אפשר גם לשים את הטאפל במשתנה מראש: basket_content = (drivers, role),
ואז "..." % basket_content.
זו השיטה הישנה. היא נפוצה מאוד, ותראו אותה בהרבה קוד. השיטה החדשה
היא המתודה format, והסרטון מפנה לקישור עליה.
8.3 · מילון
ברשימה ניגשים לערך לפי מיקום, מספר שלא אומר כלום. במילון
(dict) ניגשים לפי מפתח (key), שיש לו משמעות. כל איבר הוא זוג:
מפתח וערך (value).
>>> empty = {}
>>> type(empty)
<class 'dict'>
>>> empty = dict()
>>> keyboard_shortcuts = {"copy": "Ctrl+C",
... "paste": "Ctrl+V",
... "undo": "Ctrl+Z"}
סוגריים מסולסלים, נקודתיים בין מפתח לערך, ופסיקים בין זוגות.
| סוגריים | גישה לפי | |
|---|---|---|
| רשימה | [ ] |
מיקום |
| טאפל | ( ) |
מיקום |
| מילון | { } |
מפתח |
שליפה
>>> keyboard_shortcuts["paste"]
'Ctrl+V'
>>> keyboard_shortcuts["cut"]
Traceback (most recent call last):
...
KeyError: 'cut'
- שולפים לפי מפתח בלבד. אין שליפה הפוכה, מערך למפתח. גם במילון של מילים מחפשים את המילה, ולא את ההסבר
- מפתח שלא קיים:
KeyError. בודקים לפני עםin:
>>> "cut" in keyboard_shortcuts
False
הוספה ועדכון
מילון הוא mutable. אותה צורה מוסיפה ומעדכנת:
>>> keyboard_shortcuts["cut"] = "Ctrl+X"
>>> keyboard_shortcuts["paste"] = "Shift+Insert"
>>> keyboard_shortcuts["paste"]
'Shift+Insert'
כל מפתח ייחודי. השמה למפתח שכבר קיים לא יוצרת זוג נוסף ולא זורקת שגיאה. היא מחליפה את הערך.
מחיקה
>>> del keyboard_shortcuts["copy"]
>>> keyboard_shortcuts.pop("paste")
'Shift+Insert'
>>> keyboard_shortcuts
{'undo': 'Ctrl+Z', 'cut': 'Ctrl+X'}
del מוחק. pop מוחק ומחזיר את הערך.
לעבור על מילון
>>> keyboard_shortcuts.keys()
dict_keys(['undo', 'cut'])
>>> keyboard_shortcuts.values()
dict_values(['Ctrl+Z', 'Ctrl+X'])
>>> keyboard_shortcuts.items()
dict_items([('undo', 'Ctrl+Z'), ('cut', 'Ctrl+X')])
>>> for info in keyboard_shortcuts.items():
... print("%s: %s" % info)
...
undo: Ctrl+Z
cut: Ctrl+X
items מחזיר כל זוג כטאפל, ולכן אפשר להעביר אותו ישר לתבנית
המחרוזת. מה שחוזר מ-keys, values ו-items הוא view object:
אפשר לעבור עליו בלולאה, והוא לא העתק של המילון.
בדיקה עצמית
- מה הטיפוס של
("a")? ושל("a",)? - מה ידפיס
"%s is %d" % ("pi", 3)? - מה קורה ב-
d = {"a": 1}ואזd["a"] = 2? - במה
popשונה מ-del? - נקודה במרחב,
(x, y, z): טאפל או רשימה? ורשימת קניות?
תשובות.
1: str, ו-tuple.
2: pi is 3.
3: הערך של "a" מתעדכן ל-2. מפתח ייחודי, אז אין זוג שני.
4: pop גם מחזיר את הערך שנמחק.
5: נקודה: טאפל, כי מספר האיברים קבוע ולמיקום יש משמעות. רשימת קניות:
רשימה, כי מוסיפים ומוחקים ממנה.
טיפוסים והסבה
ארבעת הטיפוסים
| טיפוס | דוגמה | הערה |
|---|---|---|
str |
"Python", 'a' |
כל דבר במרכאות, גם "5" |
int |
2, -7 |
שלם |
float |
7.25, 7.0 |
עשרוני. 7.0 הוא float ולא int |
bool |
True, False |
אות גדולה. כל מספר שאינו 0 נחשב True |
בודקים טיפוס עם type():
>>> type(7.0)
<class 'float'>
>>> type("7")
<class 'str'>
הסבה
כותבים את הטיפוס הרצוי, ובסוגריים את הערך:
>>> int("5") ** 2
25
>>> float("5")
5.0
>>> str(3) + str(3)
'33'
>>> bool(0)
False
איפה זה תופס אתכם
input מחזיר תמיד מחרוזת. גם אם הוקלד 5, מתקבל "5". כל חישוב
על קלט צריך הסבה קודם. בלי זה:
>>> "5" ** 2
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'
+ תלוי בטיפוס. על מספרים הוא חיבור, ועל מחרוזות שרשור. 3 + 3
הוא 6, ו-"3" + "3" הוא "33".
math.sqrt מחזירה float. math.sqrt(9) הוא 3.0.
לכתוב טוב
משתנה שהתחיל כמספר לא עובר להצביע על מחרוזת. זה אפשרי, וזה bad practice: פעולה שמתאימה לטיפוס אחד נשברת על השני.
בדיקה עצמית
- מה הטיפוס של
7.0? ושל"7.0"? - מה יודפס:
print(int("4") + 1)? - למה
input("age: ") + 1נכשל?
תשובות. 1: float, ו-str. 2: 5. 3: input מחזיר מחרוזת, ואי
אפשר לחבר מחרוזת ומספר. צריך int(input("age: ")) + 1.
ביטויים לוגיים
האופרטורים
| אופרטור | שואל | x = 2 |
|---|---|---|
== |
שווה? | x == 5 הוא False |
!= |
שונה? | x != 5 הוא True |
<, >, <=, >= |
קטן, גדול | x < 4 הוא True |
not |
הופך | not x < 4 הוא False |
and |
גם וגם | נכון רק אם שני הצדדים נכונים |
or |
לפחות אחד | נכון אם צד אחד מספיק |
in |
נמצא בתוך? | "break" in "breakfast" הוא True |
ביטוי הוא ערך
תוצאה של ביטוי לוגי היא True או False, ואפשר לשים אותה במשתנה:
>>> number_of_sandwiches = 2
>>> i_am_hungry = number_of_sandwiches < 4
>>> i_am_hungry
True
and מול or
>>> cups_of_coffee = 3
>>> number_of_sandwiches < 4 and cups_of_coffee > 5
False
>>> number_of_sandwiches < 4 or cups_of_coffee > 5
True
| צד שמאל | צד ימין | and |
or |
|---|---|---|---|
True |
True |
True |
True |
True |
False |
False |
True |
False |
True |
False |
True |
False |
False |
False |
False |
איפה זה תופס אתכם
=מול==. אחד משים, השני משווה.trueבאות קטנה אינו ערך בוליאני. פייתון תחפש משתנה בשם הזה.- 0 הוא
False, וכל מספר אחר הואTrue. גם מספר שלילי.
לכתוב טוב
ביטוי של כמה תנאים: רווח משני צדי כל אופרטור, וכל תנאי בסוגריים.
>>> bowls_of_soup = 0
>>> (((number_of_sandwiches >= 1)
... and (number_of_sandwiches < 4))
... or (bowls_of_soup == 2))
True
בדיקה עצמית
- מה התוצאה של
not (3 == 3)? - מה התוצאה של
"a" in "banana" and 5 > 7? - מה התוצאה של
bool(-1)?
תשובות. 1: False. 2: False, כי הצד הימני לא נכון. 3: True,
כי כל מספר שאינו אפס נחשב אמת.
מרכאות ותווים מיוחדים
איזו מרכאה לבחור
| המחרוזת מכילה | עוטפים ב | דוגמה |
|---|---|---|
| גרש | כפולות | "What's up" |
| מרכאות כפולות | יחידות | 'She said "maybe"' |
| גם וגם | לוכסן הפוך לפני התו | "She said \"don't\"" |
| כמה שורות | משולשות | """...""" |
הכלל שלא משתנה: המחרוזת נסגרת באותו סוג מרכאה שבו נפתחה.
התווים המיוחדים
| כותבים | מקבלים |
|---|---|
\n |
שורה חדשה |
\t |
טאב |
\", \' |
מרכאה כחלק מהטקסט |
\\ |
לוכסן הפוך אחד |
הלוכסן ההפוך נקרא escape character: הוא מנטרל את המשמעות הרגילה של התו שבא אחריו.
יצירת מחרוזת מחלקים
>>> "We " + "belong " + "together"
'We belong together'
>>> "ha" * 3
'hahaha'
>>> str(3) + "!"
'3!'
איפה זה תופס אתכם
נתיב של קובץ ב-Windows. "C:\tournaments\new.txt" מכיל \t
ו-\n, ופייתון תדפיס טאב ושורה חדשה. צריך \\ בכל מקום.
print מול הצגה באינטרפרטר. רק print מפרש את \n ו-\t. בלי
print רואים אותם כמו שהם.
רווחים בשרשור. "We" + "belong" הוא "Webelong".
בדיקה עצמית
- איך כותבים את המחרוזת
It's "fine"בפייתון? - כמה שורות יודפסו ב-
print("a\nb\nc")? - מה יוצא מ-
"-" * 5?
תשובות. 1: 'It\'s "fine"' או "It's \"fine\"", או במרכאות
משולשות. 2: שלוש. 3: '-----'.
אינדקס וחיתוך
המפה
>>> word = "gaming"
| תו | g |
a |
m |
i |
n |
g |
|---|---|---|---|---|---|---|
| מההתחלה | 0 | 1 | 2 | 3 | 4 | 5 |
| מהסוף | -6 | -5 | -4 | -3 | -2 | -1 |
הצורות
| כותבים | מקבלים | למה |
|---|---|---|
word[0] |
'g' |
התו הראשון |
word[-1] |
'g' |
התו האחרון |
word[0:2] |
'ga' |
מ-0 עד 2, בלי 2 |
word[2:5] |
'min' |
שלושה תווים: 5 - 2 |
word[:2] |
'ga' |
בלי התחלה: מ-0 |
word[2:] |
'ming' |
בלי סוף: עד הסוף |
word[:] |
'gaming' |
הכל |
word[:-1] |
'gamin' |
הכל חוץ מהאחרון |
word[::2] |
'gmn' |
כל תו שני, מ-0 |
word[1::2] |
'aig' |
כל תו שני, מ-1 |
>>> word[2:5]
'min'
>>> word[::2]
'gmn'
איפה זה תופס אתכם
הסוף לא נכלל. זו הטעות הנפוצה ביותר בחיתוך.
מתחילים מאפס. התו הראשון הוא [0], והאחרון הוא [אורך פחות 1],
או פשוט [-1].
אינדקס מחוץ לגבול נותן שגיאה, וחיתוך מחוץ לגבול לא:
>>> word[10]
Traceback (most recent call last):
...
IndexError: string index out of range
>>> word[2:100]
'ming'
מחרוזת לא ניתנת לשינוי (immutable):
>>> word[0] = "G"
Traceback (most recent call last):
...
TypeError: 'str' object does not support item assignment
>>> word = "G" + word[1:]
>>> word
'Gaming'
לא רק מחרוזות
אותה גישה ואותו חיתוך עובדים על רשימה ועל טאפל, כי גם הם רצפים (יחידות 6 ו-8). ההבדל: ברשימה כן אפשר לשנות איבר.
>>> [10, 20, 30, 40][1:3]
[20, 30]
>>> (10, 20, 30)[-1]
30
>>> nums = [10, 20, 30]
>>> nums[0] = 99
>>> nums
[99, 20, 30]
בדיקה עצמית
עם s = "python":
- מה זה
s[1:4]? - מה זה
s[-2:]? - איך מקבלים
"pto"?
תשובות. 1: 'yth'. 2: 'on'. 3: s[::2].
השגיאות שפגשנו
איך קוראים Traceback
- השורה האחרונה קודם. שם כתוב סוג השגיאה והסבר קצר
- מספר השורה אומר איפה פייתון נתקעה
- הסמן הקטן (
^) מצביע על המקום המדויק בשורה
המקום שפייתון נתקעה בו הוא לא תמיד המקום של הטעות. במרכאה שלא נסגרה, הטעות בהתחלה של השורה והגילוי בסופה.
הטבלה
| שגיאה | מה היא אומרת | איפה ראינו | התיקון |
|---|---|---|---|
SyntaxError |
הקוד לא בנוי לפי חוקי השפה | 3.1: מרכאות. 5.3: ברירת מחדל לפני פרמטר בלי | לתקן את הכתיבה |
IndentationError |
הזחה במקום הלא נכון | 4.1: רווחים בתחילת שורה | ארבעה רווחים, רק בתוך בלוק |
TypeError |
פעולה שהטיפוס לא תומך בה | 2.3, 3.3, 5.1, 6.2, 8.1 | הסבה, או טיפוס אחר |
NameError |
שם שלא מוכר כאן | 5.2: משתנה לוקאלי מחוץ לפונקציה | לבדוק איות וטווח הכרה |
IndexError |
מיקום שלא קיים | 3.3, 6.3 | לבדוק את len |
ValueError |
הערך לא מתאים | 6.3: remove של ערך שאינו ברשימה |
לבדוק עם in לפני |
KeyError |
מפתח שלא קיים במילון | 8.3 | לבדוק עם in לפני |
| שגיאה לוגית | אין הודעה. התוכנית עושה משהו אחר | 7.1: לולאה שלא נגמרת | לבדוק את ההנחות |
TypeError: חמש פנים
אותה שגיאה, חמש סיבות שונות. מה שמשותף להן: הטיפוס לא מתאים לפעולה.
>>> "5" ** 2
Traceback (most recent call last):
...
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'
>>> "Change me"[0] = "S"
Traceback (most recent call last):
...
TypeError: 'str' object does not support item assignment
>>> ("a", "b")[0] = "c"
Traceback (most recent call last):
...
TypeError: 'tuple' object does not support item assignment
>>> ["H"] + "O"
Traceback (most recent call last):
...
TypeError: can only concatenate list (not "str") to list
>>> def square(number):
... return number ** 2
...
>>> square()
Traceback (most recent call last):
...
TypeError: square() missing 1 required positional argument: 'number'
השאר
>>> 'I really hope defining this string will work"
Traceback (most recent call last):
...
SyntaxError: unterminated string literal (detected at line 1)
>>> "joker"[5]
Traceback (most recent call last):
...
IndexError: string index out of range
>>> ["Earth"].remove("Pluto")
Traceback (most recent call last):
...
ValueError: list.remove(x): x not in list
>>> {"copy": "Ctrl+C"}["cut"]
Traceback (most recent call last):
...
KeyError: 'cut'
בגרסאות ישנות ה-SyntaxError של מרכאה פתוחה מנוסח
EOL while scanning string literal, וזה מה שמופיע בסרטון.
השגיאה השקטה
answer = input("How many months? ")
while answer != 7:
answer = input("Try again: ")
התוכנית לא קורסת, ואין שום הודעה. היא פשוט שואלת לנצח, כי "7" אינו
7. שגיאה לוגית היא הקשה ביותר, כי אין מה לקרוא. מה שעוזר:
להדפיס ערכים באמצע (print(answer, type(answer))) ולבדוק את ההנחות.
בדיקה עצמית
איזו שגיאה תתקבל?
print("hello')[1, 2, 3][3]"3" + 3{"a": 1}["b"]if True:ושורה אחריה בלי הזחהdef f(): y = 1, ואזprint(y)
תשובות. 1: SyntaxError. 2: IndexError, כי המיקום האחרון הוא 2.
3: TypeError. 4: KeyError. 5: IndentationError. 6: NameError,
כי y לוקאלי.
לכתוב טוב
הקוד ירוץ גם בלי רוב הכללים האלה. פייתון לא אוכפת אותם. הם קיימים בשביל מי שיקרא את הקוד, כולל אתם בעוד חודש. המסמך שמרכז אותם הוא PEP 8. היוצא מן הכלל הוא ההזחה: שם הכלל הוא חלק מהשפה.
שמות
| כלל | נכון | לא |
|---|---|---|
| אותיות קטנות | character |
Character |
| מילים מופרדות בקו תחתון | nose_length |
noselength, noseLength |
| קבוע באותיות גדולות | PI = 3.14 |
pi = 3.14 |
| שם שאומר מה יש בו | fairy_tale_file_with_extension |
file |
| פונקציה: מה היא עושה | num_of_bottles |
f, calc |
| לא אותו שם בפנים ובחוץ | land_animal, sea_animal |
animal פעמיים |
קבוע הוא הבטחה, לא נעילה. פייתון תאפשר לשנות את PI.
רווחים והזחה
| כלל | נכון | לא |
|---|---|---|
| משני צדי אופרטור | x = a + 1 |
x=a+1 |
| אחרי פסיק | f(a, b, c) |
f(a,b,c) |
| פרמטר אחד | f(a) |
f( a ) |
| הזחה של בלוק | ארבעה רווחים | טאב, או ערבוב של שניהם |
| בין פונקציות | שתי שורות ריקות | שום רווח |
ביטוי לוגי ארוך
כל תנאי בסוגריים, ורווחים סביב האופרטורים:
(((sandwiches >= 1) and (sandwiches < 4))
or (bowls_of_soup == 2))
elif במקום קינון
שלוש אפשרויות כתובות כ-if, elif, elif, else באותה רמה, ולא
if בתוך else בתוך else.
פונקציות
- מטרה אחת לכל פונקציה
- docstring מיד אחרי ה-
def: מה היא עושה,:param:,:type:,:return:,:rtype: - קלט ופלט ברורים. ערך נכנס כארגומנט ויוצא ב-
return - לא לגעת במשתנים גלובליים מתוך פונקציה, אלא אם הם קבועים. ובטח
לא לשנות אותם עם
global
def num_of_bottles(total_liters):
"""Calculates how many 1.5 liter bottles to take.
:param total_liters: the total amount of water needed
:type total_liters: float
:return: the number of bottles
:rtype: int
"""
return math.ceil(total_liters / 1.5)
מבנה התוכנית
def main():
# the program starts here
pass
if __name__ == "__main__":
main()
הקורס מבקש את המבנה הזה בכל תוכנית מיחידה 5 והלאה.
טיפוס קבוע למשתנה
משתנה שהתחיל כמספר נשאר מספר. לעבור ממנו למחרוזת זה אפשרי, וbad practice.
בדיקה עצמית
מה לא בסדר, לפי מה שהקורס מבקש?
NumberOfStudents=30MAX_SCORE = 100, כשהערך משתנה בהמשך התוכניתprint(a,b)- פונקציה בשם
do_stuffבלי docstring, שמדפיסה את התוצאה במקום להחזיר אותה - שתי פונקציות צמודות, בלי שורה ריקה ביניהן
תשובות. 1: אותיות גדולות וחסרים רווחים, צריך
number_of_students = 30. 2: אותיות גדולות שמורות לקבוע. 3: חסר רווח
אחרי הפסיק. 4: שם שלא אומר כלום, אין תיעוד, ו-print במקום return
מונע שימוש בתוצאה. 5: צריך שתי שורות ריקות.
פונקציות ומתודות מוכנות
פונקציה מול מתודה
| פונקציה | מתודה | |
|---|---|---|
| צורה | שם(פרמטרים) |
אובייקט.שם(פרמטרים) |
| דוגמה | len(x), math.sqrt(9) |
"abc".upper(), lst.append(4) |
| שייכת ל | עומדת בפני עצמה, או בתוך ספרייה | טיפוס מסוים |
הנקודה מטעה. ב-math.sqrt היא אומרת "מתוך הספרייה math".
ב-"abc".upper() היא אומרת "המתודה של המחרוזת הזו".
פונקציות
| מה עושה | דוגמה | תוצאה | |
|---|---|---|---|
print |
מדפיס | print("a", 1) |
a 1 |
input |
קולט. מחזיר מחרוזת | input("? ") |
מה שהוקלד |
type |
הטיפוס | type(2) |
<class 'int'> |
int, float, str, bool |
הסבה | int("5") |
5 |
list, tuple, dict |
יצירה או הסבה | list("ab") |
['a', 'b'] |
len |
אורך | len([1, 2]) |
2 |
max, sum |
הגדול, הסכום | sum([1, 2]) |
3 |
sorted |
רשימה חדשה ממוינת | sorted([2, 1]) |
[1, 2] |
range |
סדרת מספרים | list(range(3)) |
[0, 1, 2] |
math.sqrt |
שורש. מחזיר float |
math.sqrt(9) |
3.0 |
help, dir |
עזרה, רשימת מתודות | dir(str) |
רשימה |
מתודות
| טיפוס | מתודה | מה עושה | משנה את המקור? |
|---|---|---|---|
| מחרוזת | upper() |
אותיות גדולות | לא, מחזירה חדשה |
| מחרוזת | zfill(n) |
אפסים משמאל | לא, מחזירה חדשה |
| רשימה | append(x) |
מוסיפה בסוף | כן, מחזירה None |
| רשימה | remove(x) |
מוחקת מופע ראשון | כן |
| רשימה | count(x) |
כמה פעמים | לא |
| רשימה | sort() |
ממיינת | כן, מחזירה None |
| מילון | pop(k) |
מוחקת ומחזירה ערך | כן |
| מילון | keys(), values(), items() |
מפתחות, ערכים, זוגות | לא |
העמודה האחרונה היא מה שבודקים במבחנים. מתודות של מחרוזת לא יכולות
לשנות אותה, כי מחרוזת היא immutable. מתודות של רשימה ומילון כן, והן
בדרך כלל מחזירות None.
>>> s = "hi"
>>> s.upper()
'HI'
>>> s
'hi'
>>> lst = [2, 1]
>>> print(lst.sort())
None
>>> lst
[1, 2]
פרמטרים אופציונליים
חלק מהפונקציות מקבלות פרמטרים שלא חייבים לשלוח:
>>> sorted(["moon", "asteroid", "galaxy"], key=len)
['moon', 'galaxy', 'asteroid']
>>> print("a", "b", end="!\n")
a b!
מה כל פונקציה מקבלת: help(sorted), או התיעוד של פייתון.
איפה מחפשים
help(): ממשק עזרה. רווח מדפדף,qיוצאhelp(sorted): ישר לפונקציה, וגם לפונקציות שכתבתם, אם יש להן docstringdir(list): כל המתודות של רשימה- אינטרנט: רק תיעוד של פייתון 3
בדיקה עצמית
- מה יחזיר
"42".zfill(6)? - מה יודפס:
x = [3, 1],y = x.sort(),print(y)? - מה ההבדל בין
sorted(lst)לביןlst.sort()? - מה התוצאה של
len({"a": 1, "b": 2})?
תשובות. 1: '000042'. 2: None. 3: sorted מחזירה רשימה חדשה
ולא נוגעת במקור. sort משנה את המקור ומחזירה None. 4: 2, מספר
הזוגות.
תנאים ולולאות
שלוש הצורות
| מה עושה | מתי | |
|---|---|---|
if / elif / else |
בוחר בלוק אחד | החלטה |
while |
חוזר כל עוד תנאי נכון | לא יודעים כמה פעמים |
for |
חוזר פעם לכל איבר ברצף | רשימה, מחרוזת, range |
לכולן אותו מבנה: שורת פקודה שמסתיימת בנקודתיים, ובלוק מוזח בארבעה רווחים.
if
>>> grade = 85
>>> if grade >= 90:
... print("A")
... elif grade >= 80:
... print("B")
... else:
... print("C")
...
B
- הבדיקה לפי הסדר, ועוצרת בראשון שמתקיים.
85 >= 80נבדק רק כי85 >= 90נכשל elifו-elseלא חובה.elseרק אחד, ותמיד אחרון
while
>>> count = 3
>>> while count > 0:
... print(count)
... count -= 1
...
3
2
1
משהו בתוך הלולאה חייב לשנות את התנאי. אחרת היא לא תיגמר.
for
>>> for letter in "abc":
... print(letter)
...
a
b
c
>>> for i in range(1, 10, 4):
... print(i)
...
1
5
9
range(start, stop, step), ו-stop לא נכלל. כמו בחיתוך.
break ו-continue
>>> for n in range(10):
... if n == 3:
... continue
... if n == 6:
... break
... print(n, end=" ")
...
0 1 2 4 5
continue דילג על 3. break עצר ב-6, ולכן 6 עד 9 לא הודפסו.
איפה זה תופס אתכם
inputבתנאי.if input() == 5לא יתקיים אף פעם.int(input())=בתנאי.if x = 5:הואSyntaxError. צריך==- שכחתם לקדם את המונה ב-
while: לולאה אינסופית. Ctrl+C עוצר inשלforאינוinשל בדיקה. ב-for x in lstהוא משים. ב-if x in lstהוא שואל- משתנה שנוצר רק בתוך
ifלא קיים אם הבלוק לא רץ
בדיקה עצמית
- כמה פעמים ירוץ
for i in range(3, 3):? - מה ידפיס
for c in "hey": print(c * 2)? - מה חסר כאן:
while x < 10: print(x)? - איך מדפיסים רק את המספרים הזוגיים בין 0 ל-10, בשורה אחת של
for?
תשובות. 1: אפס פעמים. ההתחלה כבר שווה לסוף. 2: hh, ee, yy.
3: שורה שמגדילה את x. 4: for n in range(0, 11, 2): print(n).
לכתוב פונקציות
השלד
>>> def greet(name, greeting="Hello"):
... """Builds a greeting.
...
... :param name: who to greet
... :type name: str
... :param greeting: the opening word
... :type greeting: str
... :return: the full greeting
... :rtype: str
... """
... return greeting + ", " + name
...
>>> greet("Noa")
'Hello, Noa'
>>> greet("Noa", "Hi")
'Hi, Noa'
>>> greet(greeting="Hey", name="Noa")
'Hey, Noa'
| חלק | מה זה |
|---|---|
def greet(...): |
הגדרה. לא מריצה כלום |
name |
פרמטר חובה |
greeting="Hello" |
פרמטר עם ברירת מחדל. רק אחרי פרמטרי החובה |
"""...""" |
docstring. help(greet) מציג אותו |
return |
מה שהפונקציה מחזירה |
greet("Noa") |
קריאה. "Noa" הוא הארגומנט |
greeting="Hey" |
ארגומנט לפי שם. הסדר לא משנה |
print או return
print |
return |
|
|---|---|---|
| מה קורה | מוצג על המסך | חוזר למי שקרא |
| אפשר לשמור במשתנה | לא | כן |
| מה הפונקציה מחזירה | None |
את הערך |
>>> def show(x):
... print(x * 2)
...
>>> def give(x):
... return x * 2
...
>>> a = show(5)
10
>>> b = give(5)
>>> print(a, b)
None 10
כמעט תמיד רוצים return. פונקציה שמחזירה ערך אפשר לשלב בחישוב,
בתנאי, או בפונקציה אחרת.
כמה ערכים
>>> def min_max(numbers):
... return min(numbers), max(numbers)
...
>>> low, high = min_max([4, 9, 1])
>>> low, high
(1, 9)
חוזר טאפל, ופורקים אותו לכמה משתנים.
טווח הכרה
| מוגדר | מוכר | |
|---|---|---|
| גלובלי | מחוץ לפונקציות | בכל מקום |
| לוקאלי | בתוך פונקציה | רק בתוכה |
>>> x = "global"
>>> def f():
... x = "local"
... return x
...
>>> f()
'local'
>>> x
'global'
השמה בתוך פונקציה יוצרת משתנה לוקאלי חדש, גם אם יש גלובלי באותו
שם. לוקאלי קודם לגלובלי. global x משנה את זה, וזה לא מומלץ.
פונקציה היא אובייקט
>>> double = give
>>> double(7)
14
>>> sorted(["ccc", "a", "bb"], key=len)
['a', 'bb', 'ccc']
שם בלי סוגריים הוא הפונקציה עצמה. כך מעבירים len ל-key.
איפה זה תופס אתכם
- שכחתם סוגריים:
greetלא מריץ כלום, ואין שגיאה - שכחתם ארגומנט:
TypeError: ... missing 1 required positional argument - ברירת מחדל באמצע:
def f(a=1, b):הואSyntaxError - משתנה לוקאלי מבחוץ:
NameError printבמקוםreturn: הפונקציה מחזירהNone, ומה שבא אחריה נשבר
בדיקה עצמית
- מה מחזירה
def f(): pass? - האם מותר
def f(a, b=2, c=3):? - עם
greetמלמעלה: מה יחזירgreet("Dan", greeting="Yo")? def add(a, b): print(a + b), ואזtotal = add(1, 2) * 2. מה יקרה?
תשובות. 1: None. 2: כן. כל הפרמטרים עם ברירת המחדל בסוף. 3: 'Yo,
Dan'. 4: יודפס 3, ואז TypeError, כי add מחזירה None, ואי אפשר
להכפיל None.
מבני נתונים: איזה מתי
הטבלה
| מחרוזת | רשימה | טאפל | מילון | |
|---|---|---|---|---|
| כתיבה | "abc" |
[1, "a"] |
(1, "a") |
{"k": 1} |
| ריק | "" |
[] או list() |
() או tuple() |
{} או dict() |
| מה בפנים | תווים | כל דבר | כל דבר | זוגות מפתח וערך |
| גישה | s[0] |
l[0] |
t[0] |
d["k"] |
| חיתוך | כן | כן | כן | לא |
len, in, for |
כן | כן | כן | כן, על המפתחות |
+ ו-* |
כן | כן | כן | לא |
| שינוי | לא | כן | לא | כן |
| איבר אחד | "a" |
[1] |
(1,) |
{"k": 1} |
mutable או immutable
immutable: מחרוזת וטאפל. כל "שינוי" יוצר אובייקט חדש.
mutable: רשימה ומילון. אפשר להוסיף, לשנות ולמחוק במקום.
>>> s = "cat"
>>> s.upper()
'CAT'
>>> s
'cat'
>>> lst = ["c", "a", "t"]
>>> lst.append("s")
>>> lst
['c', 'a', 't', 's']
upper לא שינתה את s, והחזירה מחרוזת חדשה. append שינתה את lst,
והחזירה None. זה ההבדל שהכי קל להתבלבל בו.
איך בוחרים
| השאלה | אם כן |
|---|---|
| זה טקסט? | מחרוזת |
| מוסיפים ומוחקים לאורך התוכנית? | רשימה |
| מספר איברים קבוע, ולמיקום יש משמעות? | טאפל. נקודה (x, y), תאריך |
| מחפשים לפי שם ולא לפי מיקום? | מילון. קיצורי מקלדת, ציונים לפי סטודנט |
דוגמה: אותו מידע, ארבע צורות
>>> name = "Python"
>>> scores = [90, 75, 88]
>>> point = (5, 2)
>>> grades = {"math": 90, "history": 75}
>>> name[0], scores[0], point[0], grades["math"]
('P', 90, 5, 90)
הסבות ביניהם
>>> list("abc")
['a', 'b', 'c']
>>> tuple([1, 2])
(1, 2)
>>> list({"a": 1, "b": 2})
['a', 'b']
>>> list({"a": 1}.items())
[('a', 1)]
list על מילון מחזיר את המפתחות.
בדיקה עצמית
- איזה מבנה מתאים לרשימת המשימות של היום, שמוסיפים לה ומוחקים ממנה?
- איזה מבנה מתאים לשמירת צבע כשלושה מספרים,
(255, 0, 0)? - מה ההבדל בין
[1]לבין(1)? - מה יחזיר
len({"a": 1, "b": 2}), ומה יחזירlen("ab")?
תשובות. 1: רשימה. 2: טאפל. מספר קבוע, ולכל מקום יש משמעות. 3:
[1] הוא רשימה. (1) הוא פשוט 1. טאפל צריך פסיק, (1,). 4: שניהם
2.
דוגמאות
אלה לא התרגילים של הקורס. הן נכתבו כאן כדי לראות איך הנושאים מתחברים, ובכל אחת כתוב מאיזו יחידה מגיע כל חלק. נסו לפתור לבד קודם, ורק אחר כך לקרוא את הפתרון.
1. ממוצע וציון
המשימה: פונקציה שמקבלת רשימת ציונים, ומחזירה את הממוצע ואת הציון במילה.
יחידות: 4, 5, 6.
>>> def grade_report(grades):
... """Returns the average and a word for it.
...
... :param grades: the grades
... :type grades: list
... :return: the average and the word
... :rtype: tuple
... """
... average = sum(grades) / len(grades)
... if average >= 90:
... word = "excellent"
... elif average >= 70:
... word = "good"
... else:
... word = "needs work"
... return average, word
...
>>> grade_report([95, 80, 72])
(82.33333333333333, 'good')
מה לשים לב: word מקבל ערך בכל אחד משלושת הענפים. אם היה חסר
else, ממוצע נמוך היה משאיר את word בלי ערך, ו-return היה נותן
UnboundLocalError, סוג של NameError. זו המלכודת שפרק 4.2 מזכיר.
2. ספירת מילים
המשימה: כמה פעמים כל מילה מופיעה ברשימה.
יחידות: 7, 8.
>>> def count_words(words):
... counts = {}
... for word in words:
... if word in counts:
... counts[word] += 1
... else:
... counts[word] = 1
... return counts
...
>>> count_words(["to", "be", "or", "not", "to", "be"])
{'to': 2, 'be': 2, 'or': 1, 'not': 1}
מה לשים לב: בלי הבדיקה if word in counts, הפעם הראשונה של כל מילה
הייתה נותנת KeyError, כי אין עוד מה להגדיל.
3. ניחוש מספר
המשימה: לבקש מהמשתמש לנחש עד שיצליח, ולספור ניסיונות.
יחידות: 2, 4, 5, 7.
SECRET = 7
def main():
attempts = 0
while True:
guess = int(input("Guess a number: "))
attempts += 1
if guess == SECRET:
print("Got it in %d tries" % attempts)
break
elif guess < SECRET:
print("Higher")
else:
print("Lower")
if __name__ == "__main__":
main()
מה לשים לב:
int(...)סביבinput. בלעדיו זו בדיוק השגיאה הלוגית מפרק 7.1SECRETבאותיות גדולות, כי זה קבוע. ומותר לקרוא אותו מתוך הפונקציה, כי זה קבוע (פרק 5.2)while Trueעםbreakכשיש יציאה ברורה מבפנים
4. מילה הפוכה ופלינדרום
המשימה: האם מילה זהה כשקוראים אותה מהסוף.
יחידות: 3, 5.
>>> def is_palindrome(word):
... word = word.lower()
... return word == word[::-1]
...
>>> is_palindrome("Level")
True
>>> is_palindrome("Python")
False
מה לשים לב: return word == word[::-1] מחזיר את תוצאת ההשוואה
ישירות. אין צורך ב-if ...: return True else: return False. ו-lower,
אחות של upper, כדי ש-L ו-l ייחשבו שווים.
5. מלאי
המשימה: מילון של מוצרים וכמויות. להדפיס את מה שנגמר.
יחידות: 7, 8.
>>> stock = {"apples": 12, "bread": 0,
... "milk": 3, "eggs": 0}
>>> for item, amount in stock.items():
... if amount == 0:
... print("Out of %s" % item)
...
Out of bread
Out of eggs
מה לשים לב: for item, amount in stock.items() פורק כל זוג לשני
משתנים, אותו פירוק כמו ב-a, b = b, a. הסרטון עובר על items עם משתנה
אחד, ושני הסגנונות עובדים.
6. ממיר טמפרטורות
המשימה: רשימה של מעלות צלזיוס, ורשימה חדשה בפרנהייט.
יחידות: 5, 6, 7.
>>> def to_fahrenheit(celsius_list):
... result = []
... for c in celsius_list:
... result.append(c * 9 / 5 + 32)
... return result
...
>>> to_fahrenheit([0, 100, 37])
[32.0, 212.0, 98.6]
מה לשים לב: result = [] לפני הלולאה. אם היה בתוכה, הרשימה הייתה
מתאפסת בכל איטרציה. ו-return result מחוץ ללולאה, אחרת הפונקציה הייתה
חוזרת אחרי האיבר הראשון.
דף עזר
טיפוסים
| דוגמה | הסבה | שינוי | |
|---|---|---|---|
str |
"Python" |
str(3) הוא '3' |
לא |
int |
2 |
int("5") הוא 5 |
|
float |
7.25 |
float("5") הוא 5.0 |
|
bool |
True |
bool(0) הוא False |
|
list |
[1, "a"] |
list("ab") |
כן |
tuple |
(1, "a"), (1,) |
tuple([1, 2]) |
לא |
dict |
{"k": 1} |
dict() |
כן |
אופרטורים
+ - * / ** |
חשבון. ** חזקה |
% |
שארית. n % 2 == 0 פירושו זוגי |
+=, -= |
x += 1 הוא x = x + 1 |
+ על רצפים |
שרשור, רק מאותו טיפוס |
* על רצף ומספר |
הכפלה: "ab" * 2 הוא 'abab' |
== != < > <= >= |
השוואה |
not and or |
לוגיקה |
in |
הכלה: "b" in "abc", 3 in [1, 3], "k" in d |
רצפים: מחרוזת, רשימה, טאפל
s[0], s[-1] |
ראשון, אחרון |
s[a:b] |
מ-a עד b, בלי b |
s[:b], s[a:], s[:] |
מההתחלה, עד הסוף, הכל |
s[a:b:k] |
בקפיצות של k. s[::-1] הפוך |
len(s) |
אורך |
s.upper(), s.zfill(n) |
מחרוזת: גדולות, אפסים משמאל |
\n \t \\ \" |
שורה, טאב, לוכסן, מרכאה |
"%s is %d" % (a, b) |
תבנית מחרוזת |
רשימה
lst.append(x) |
מוסיף בסוף. מחזיר None |
lst += [x, y] |
מוסיף כמה |
lst[i] = x |
מחליף. רק במיקום קיים |
lst.remove(x) |
מוחק מופע ראשון. לא קיים: ValueError |
lst.count(x) |
כמה פעמים |
lst.sort() |
ממיין את הרשימה עצמה |
sorted(lst, key=len) |
רשימה חדשה ממוינת |
max(lst), sum(lst) |
הגדול, הסכום |
מילון
d["k"] |
ערך לפי מפתח. לא קיים: KeyError |
d["k"] = v |
מוסיף, או מעדכן אם קיים |
del d["k"] |
מוחק |
d.pop("k") |
מוחק ומחזיר את הערך |
d.keys(), d.values(), d.items() |
מפתחות, ערכים, זוגות כטאפלים |
תנאים ולולאות
if / elif / else |
הראשון שמתקיים, ורק הוא |
while תנאי: |
כל עוד |
for x in רצף: |
פעם לכל איבר |
range(start, stop, step) |
סדרה. stop לא נכלל |
break |
יוצא מהלולאה |
continue |
מדלג לאיטרציה הבאה |
pass |
בלוק ריק |
פונקציות
def f(a, b=2): |
הגדרה. ברירות מחדל בסוף |
return x, y |
מחזיר. כמה ערכים חוזרים כטאפל |
בלי return |
מחזיר None |
f(b=5, a=1) |
ארגומנטים לפי שם |
"""...""" |
docstring: :param: :type: :return: :rtype: |
global x |
משנה משתנה גלובלי. לא מומלץ |
if __name__ == "__main__": main() |
מבנה התוכנית |
פקודות
print(a, b, end=" ") |
הדפסה |
input("...") |
קלט. תמיד מחרוזת |
type(x) |
הטיפוס |
import math, math.sqrt(x) |
שורש, float |
help(f), f.__doc__ |
תיעוד. q יוצא |
dir(str) |
המתודות |
a, b = b, a |
החלפה |
שגיאות
SyntaxError |
כתיבה לא תקינה |
IndentationError |
הזחה לא במקום |
TypeError |
טיפוס לא מתאים לפעולה |
NameError |
שם לא מוכר, או מחוץ לטווח |
IndexError |
מיקום לא קיים |
ValueError |
ערך לא מתאים, למשל remove |
KeyError |
מפתח לא קיים |
PEP 8
snake_case |
משתנים ופונקציות |
UPPER_CASE |
קבועים |
| ארבעה רווחים | הזחה |
x = a + b, f(a, b) |
רווחים |
| שתי שורות ריקות | בין פונקציות |
מילון מונחים
| עברית | אנגלית | פירוש |
|---|---|---|
| משתנה | variable | שם שמצביע על אובייקט |
| השמה | assignment | =. קישור שם לערך |
| טיפוס | type | סוג האובייקט: int, str ועוד |
| מחרוזת | string | רצף תווים |
| בוליאני | boolean | True או False |
| הסבה | casting | המרה בין טיפוסים |
| קבוע | constant | ערך שלא משתנה. בקונבנציה, אותיות גדולות |
| קונבנציה | convention | מוסכמה. לא נאכפת על ידי השפה |
| תו בריחה | escape character | \. מנטרל את המשמעות של התו הבא |
| אינדקס | index | מיקום ברצף, מאפס |
| חיתוך | slicing | [a:b] |
| רצף | sequence | מחרוזת, רשימה, טאפל |
| ניתן לשינוי | mutable | רשימה, מילון |
| לא ניתן לשינוי | immutable | מחרוזת, טאפל |
| בלוק | block | שורות מוזחות שמתחת לשורה עם נקודתיים |
| הזחה | indentation | הרווחים בתחילת השורה |
| בקרת זרימה | flow control | if, לולאות, break |
| איטרציה | iteration | סבב אחד של לולאה |
| פונקציה | function | בלוק עם שם, שמבצע משימה |
| מתודה | method | פונקציה של טיפוס: x.upper() |
| פרמטר | parameter | השם בהגדרה |
| ארגומנט | argument | הערך בקריאה |
| ערך החזרה | return value | מה ש-return מחזיר |
| ברירת מחדל | default | ערך לפרמטר שלא נשלח |
| טווח הכרה | scope | איפה משתנה קיים |
| גלובלי, לוקאלי | global, local | מחוץ לפונקציה, בתוכה |
| תיעוד | docstring | ההסבר שבתוך הפונקציה |
| טאפל | tuple | רצף שלא ניתן לשינוי |
| מילון | dictionary | זוגות של מפתח וערך |
| שגיאה לוגית | logic error | בלי הודעה. התוכנית עושה משהו אחר |
| אינטרפרטר | interpreter | מקום להריץ שורה אחרי שורה |
סיכום הקורס
יחידה אחרי יחידה
| יחידה | נושא | מה אפשר לעשות אחריה |
|---|---|---|
| 2 | משתנים | לשמור ערכים, לחשב, לקלוט מהמשתמש |
| 3 | מחרוזות | לבנות טקסט, לחתוך אותו, להשתמש במתודות |
| 4 | תנאים | להחליט מה ירוץ |
| 5 | פונקציות | לכתוב קוד פעם אחת ולהשתמש בו שוב |
| 6 | רשימות | להחזיק הרבה ערכים ולשנות אותם |
| 7 | לולאות | לחזור על פעולה בלי לכתוב אותה שוב |
| 8 | טאפל ומילון | לבחור את מבנה הנתונים שמתאים למידע |
יחידות 0 ו-1 הן פתיחה והיכרות עם הסביבה, ולא נכנסו לכאן. יחידות 9 (קבצים) ו-10 (פרויקט מסכם) עוד לא סוכמו.
שלושה רעיונות שחוזרים
1. משתנה מצביע, הוא לא מכיל
יחידה 2 פותחת בזה: course = "Python" יוצר אובייקט, ו-course מצביע
עליו. כל השאר נגזר מזה:
- "לשנות" מחרוזת זה להצביע על מחרוזת חדשה (3.3)
- פונקציה היא אובייקט, ושם בלי סוגריים מצביע עליה (5.1)
a, b = b, aרק מחליף הצבעות (2.3, 8.2)
2. מה משתנה ומה לא
| לא ניתן לשינוי | ניתן לשינוי |
|---|---|
| מחרוזת, טאפל | רשימה, מילון |
מתודה מחזירה חדש: s.upper() |
מתודה משנה במקום: lst.sort() |
השאלה "האם זה משנה את המקור, או מחזיר חדש?" עונה על חלק גדול מהבלבולים בקורס.
3. input מחזיר מחרוזת
זה מופיע ביחידה 2, ושוב ב-4, ושוב ב-7, כל פעם בצורה אחרת: TypeError
בחישוב, תנאי שלא מתקיים, ולולאה שלא נגמרת. בכל פעם שיש input ומספר,
צריך int.
הרגלים שהקורס מבקש
- שמות
snake_caseשאומרים מה יש בהם - ארבעה רווחים להזחה
- docstring לכל פונקציה
mainו-if __name__ == "__main__"בכל תוכנית- לבדוק עם
inלפניremoveולפני שליפה ממילון
לחזרה לפני מבחן
- השגיאות שפגשנו: לזהות שגיאה מההודעה
- מבני נתונים: הטבלה שמשווה את ארבעתם
- לכתוב פונקציות:
printמולreturn, וטווח הכרה - דוגמאות: לפתור לבד, ואז להשוות
- דף עזר: הכל בעמוד אחד