הקדמה
ברוכים הבאים למדריך האינטרנטי של Google ל-Python. הוא מבוסס על קורס המבוא ל-Python שאנחנו מציעים באופן פנימי. כפי שצוין בדף ההגדרה, החומר הזה עוסק ב-Python 3.
אם אתם מחפשים קורס נלווה לקורס MOOC, תוכלו לנסות את הקורסים של Udacity ו-Coursera (מבוא לתכנות [Gettings] או מבוא ל-Python). לסיום, אם אתם מחפשים למידה אונליין בקצב אישי בלי צפייה בסרטונים, כדאי לנסות את אלה שמפורטים בסוף הפוסט הזה — כל תוכן לימודי וגם מתורגמן אינטראקטיבי ב-Python שאפשר לתרגל איתו. מהו 'המתורגמן' שאנחנו מזכירים? בקטע הבא נסביר איך עושים את זה.
מבוא לשפה
Python היא שפה דינמית, מפורשת (עם הידור באמצעות בייטקוד). אין הצהרות על סוגים של משתנים, פרמטרים, פונקציות או שיטות בקוד המקור. כך הקוד קצר וגמיש, ותאבדו את הבדיקה של סוג זמן ההידור של קוד המקור. Python עוקבת אחרי סוגי כל הערכים בזמן הריצה ומסמנת קוד שלא הגיוני בזמן שהוא פועל.
דרך מצוינת לראות איך קוד Python פועל היא להריץ את רכיב התרגום ב-Python ולהקליד קוד ישירות בתוכו. אם יש לכם שאלה כמו "מה יקרה אם אוסיף int
ל-list
?", הדרך המהירה והטובה ביותר לבדוק מה יקרה היא פשוט להקליד את השאלה במהמתר Python. (בהמשך אפשר לראות מה באמת קורה!)
$ python3 ## Run the Python interpreter Python 3.X.X (XXX, XXX XX XXXX, XX:XX:XX) [XXX] on XXX Type "help", "copyright", "credits" or "license" for more information. >>> a = 6 ## set a variable in this interpreter session >>> a ## entering an expression prints its value 6 >>> a + 2 8 >>> a = 'hi' ## 'a' can hold a string just as well >>> a 'hi' >>> len(a) ## call the len() function on a string 2 >>> a + len(a) ## try something that doesn't work Traceback (most recent call last): File "", line 1, in TypeError: can only concatenate str (not "int") to str >>> a + str(len(a)) ## probably what you really wanted 'hi2' >>> foo ## try something else that doesn't work Traceback (most recent call last): File " ", line 1, in NameError: name 'foo' is not defined >>> ^D ## type CTRL-d to exit (CTRL-z in Windows/DOS terminal)
שתי השורות ש-Python מדפיס אחרי שמקלידים python ולפני ההנחיה >>> מפורטות בהן גרסת Python שבה אתם משתמשים והמקום שבו היא נוצרה. כל עוד הדבר הראשון שמודפס הוא 'Python 3', הדוגמאות האלה יעבדו בשבילכם.
כפי שאפשר לראות למעלה, קל להתנסות עם משתנים ואופרטורים. בנוסף, המפרש גורם לשגיאה זמן ריצה אם הקוד מנסה לקרוא משתנה שלא הוקצה לו ערך. כמו C++ ו-Java, גם Python היא שפה רגישה לרישיות, כך ש-'a' ו-'A' הם משתנים שונים. סוף השורה מסמן את סוף ההצהרה, ולכן בניגוד ל-C++ ול-Java, ב-Python אין צורך בנקודה-פסיק בסוף כל הצהרה. תגובות מתחילות בסימן # ומסתיימות בסוף השורה.
קוד המקור של Python
קובצי מקור של Python משתמשים בתוסף ' .py' ונקראים 'מודולים'. כדי להריץ מודול Python בשם hello.py
, הדרך הקלה ביותר היא להשתמש בפקודת המעטפת 'python hello.py Alice'. הפקודה הזו קוראת למפרש Python כדי להריץ את הקוד ב-hello.py
, ומעבירה לו את הארגומנט של שורת הפקודה 'Alice'.
בדף המסמכים הרשמי מפורטות כל האפשרויות השונות להרצת Python משורת הפקודה.
הנה תוכנית hello.py
פשוטה מאוד (שימו לב שקטעי הקוד מופרדים באמצעות הכנסה לתוך השורה ולא באמצעות סוגריים מסולסלים – נרחיב על כך בהמשך):
#!/usr/bin/python3 # import modules used here -- sys is a very standard one import sys # Gather our code in a main() function def main(): print('Hello there', sys.argv[1]) # Command line args are in sys.argv[1], sys.argv[2] ... # sys.argv[0] is the script name itself and can be ignored # Standard boilerplate to call the main() function to begin # the program. if __name__ == '__main__': main()
הרצת תוכנית זו משורת הפקודה נראית כך:
$ python3 hello.py Guido Hello there Guido $ ./hello.py Alice ## without needing 'python3' first (Unix) Hello there Alice
ייבוא, ארגומנטים בשורת הפקודה ו-len()
ההצהרות החיצוניות ביותר בקובץ Python, או ב'מודול', מבצעות את ההגדרה החד-פעמית שלו – ההצהרות האלה פועלות מלמעלה למטה בפעם הראשונה שהמודול מיובא למקום כלשהו, ומגדירות את המשתנים והפונקציות שלו. אפשר להריץ מודול Python ישירות – כמו למעלה python3 hello.py Bob
– או לייבא אותו ולאפשר למודול אחר להשתמש בו. כשמפעילים קובץ Python ישירות, המשתנה המיוחד __name__ מוגדר כ-__main__. לכן, מקובל להשתמש בקוד הסטנדרטי if __name__ ==...
שמוצג למעלה כדי לקרוא לפונקציה main() כשהמודול מופעל ישירות, אבל לא כשהמודול מיובא על ידי מודול אחר.
בתוכנית Python רגילה, הרשימה sys.argv
מכילה את הארגומנטים של שורת הפקודה באופן הסטנדרטי, כאשר sys.argv[0] הוא התוכנית עצמה, sys.argv[1] הוא הארגומנט הראשון וכן הלאה. אם אתם יודעים מהו argc
או מספר הארגומנטים, אתם יכולים לבקש את הערך הזה מ-Python באמצעות len(sys.argv)
, בדיוק כמו שעשינו בקוד של הממשק האינטראקטיבי של המהדר למעלה כשביקשנו את אורך המחרוזת. באופן כללי, הפונקציה len()
יכולה להראות לכם מה האורך של מחרוזת, את מספר הרכיבים ברשימות ובצמדים (מבנה נתונים אחר דמוי מערך) ואת מספר צמדי מפתח/ערך במילון.
פונקציות מוגדרות על ידי המשתמש
הפונקציות ב-Python מוגדרות כך:
# Defines a "repeat" function that takes 2 arguments. def repeat(s, exclaim): """ Returns the string 's' repeated 3 times. If exclaim is true, add exclamation marks. """ result = s + s + s # can also use "s * 3" which is faster (Why?) if exclaim: result = result + '!!!' return result
שימו לב גם לכך שהשורות שמרכיבות את הפונקציה או משפט ה-if מקובצות לפי רמת הפסקה זהה. הצגנו גם 2 דרכים שונות לחזור על מחרוזות, באמצעות האופרטור + שהוא ידידותי יותר למשתמש, אבל גם * עובד כי זהו האופרטור 'repeat' ב-Python. כלומר, '-' * 10
נותן '----------'
, דרך נוחה ליצור 'שורה' במסך. בהערה לקוד, רמזנו ש-* פועל מהר יותר מ-+, כי הפונקציה * מחשבת את הגודל של האובייקט שנוצר פעם אחת, ואילו הפונקציה + מבצעת את החישוב הזה בכל פעם שמפעילים אותה. גם + וגם * נקראים 'אופרטורים עם עומס יתר' כי הם מסמנים דברים שונים במספרים לעומת מחרוזות (וסוגי נתונים אחרים).
מילת המפתח def
מגדירה את הפונקציה עם הפרמטרים שלה בסוגריים, והקוד שלה מוגדר עם הפסקה. השורה הראשונה של פונקציה יכולה להיות מחרוזת תיעוד (docstring) שמתארת את הפעולה שהפונקציה מבצעת. התיאור יכול להיות שורה אחת או תיאור בכמה שורות, כמו בדוגמה שלמעלה. (כן, אלה "מילות ייעודיות לקוד", תכונה ייחודית ל-Python!) משתנים שמוגדרים בפונקציה הם מקומיים לאותה פונקציה, לכן ה"תוצאה" בפונקציה שלמעלה נפרדת מהמשתנה "result" (תוצאה) בפונקציה אחרת. אפשר להעביר לטיעון של return
ארגומנט, ובמקרה כזה זהו הערך שיוחזר למבצע הקריאה.
זהו קוד שמפעיל את הפונקציה repeat() שלמעלה ומדפיס את מה שהיא מחזירה:
def main(): print(repeat('Yay', False)) ## YayYayYay print(repeat('Woo Hoo', True)) ## Woo HooWoo HooWoo Hoo!!!
בזמן הריצה, צריך להגדיר פונקציות על ידי ביצוע של 'def' לפני שמפעילים אותן. מקובל להגדיר את הפונקציה main() בתחתית הקובץ, עם הפונקציות שהיא קוראת אליהן מעליו.
כניסת פסקה
אחת מהתכונות החריגות של Python היא שההכנסה של מרווחים לקוד משפיעה על המשמעות שלו. לכל הפסקות הקטע של משפטים לוגיים, כמו אלה שמרכיבים פונקציה, צריכה להיות אותה הפסקה, שמוגדרת מהפסקה של פונקציית ההורה או של 'if' או כל דבר אחר. אם באחת מהשורות בקבוצה יש כניסת פסקה שונה, היא מסומנת כשגיאת תחביר.
השימוש של Python במרווחים לבן נראה קצת מוזר בהתחלה, אבל הוא הגיוני והתרגלתי אליו מהר מאוד. מומלץ להימנע משימוש במקש TAB כי הוא מסבך מאוד את הסכימה של הפסקה (בלי לדבר על כך שמקש TAB עשוי להיות בעל משמעות שונה בפלטפורמות שונות). מגדירים את העורך כך שיוסיף רווחים במקום TABs בקוד Python.
שאלה נפוצה של מתחילים היא "כמה רווחים צריך להוסיף לפסיק?" לפי מדריך הסגנון הרשמי של Python (PEP 8), צריך להוסיף כניסת פיסקה באמצעות 4 רווחים. (עובדה מעניינת: בהנחיות הפנימיות של Google לגבי סגנון כתיבה מצוין שצריך להוסיף 2 רווחים לפני הפסקה!)
בדיקת הקוד בזמן ריצה
ב-Python מתבצעות מעט מאוד בדיקות בזמן הידור, והמערכת דוחה כמעט את כל הבדיקות של סוגים, שמות וכו' בכל שורה עד שהשורה הזו מופעלת. נניח ש-main() שלמעלה קורא ל-repeat() כך:
def main(): if name == 'Guido': print(repeeeet(name) + '!!!') else: print(repeat(name))
המשפט if-if מכיל שגיאה מובהקת, שבה הפונקציה Return() מוזנת בטעות כ-repeeeet(). הדבר המצחיק ב-Python ... הקוד הזה עובר הידור ופועל כמו שצריך כל עוד השם בזמן הריצה הוא לא 'Guido'. רק כשהרצת הקוד תנסה לבצע את repeeeet() בפועל, היא תבחין שאין פונקציה כזו ותשלח הודעת שגיאה. יש גם שגיאה שנייה בקטע הקוד הזה. לא הוקצה ערך למשתנה name לפני שהוא הושווה ל-'Guido'. אם תנסו להעריך משתנה שלא הוקצה, תופיע הודעת השגיאה NameError ב-Python. אלה כמה דוגמאות שממחישות שבפעם הראשונה שמריצים תוכנית Python, חלק מהשגיאות הראשונות שיופיעו יהיו שגיאות הקלדה פשוטות או משתנים שלא הועברו ל-uninitialized, כמו אלה. זה תחום אחד שבו לשפות עם מערכת סוגים מפורטת יותר, כמו Java, יש יתרון ... הן יכולות לזהות שגיאות כאלה בזמן ההידור (אבל כמובן שצריך לשמור על כל הנתונים מהסוג הזה ... זה עניין יחסי).
ב-Python 3 נוסף רמזים לטיפוס.
טיפים לגבי סוגים מאפשרים לציין את הסוג של כל ארגומנט בפונקציה, וגם את הסוג של האובייקט שהפונקציה מחזירה.
לדוגמה, בפונקציה def is_positive(n: int) -> bool:
עם ההערות, הארגומנט n
הוא int
והערך המוחזר הוא bool
.
בהמשך נפרט את המשמעות של סוגי המידע האלה. עם זאת, הוספת רמזים לסוגים היא אופציונלית לחלוטין.
יותר ויותר קוד יכלול הצעות לסוגים, כי אם משתמשים בהן, חלק מהעורכים כמו cider-v ו-VS.code יכולים להריץ בדיקות כדי לוודא שהפונקציות נקראות עם סוגי הארגומנטים הנכונים. הם יכולים אפילו להציע טענות נכוֹנוּת ולתקף אותן בזמן העריכה של הקוד.
במדריך הזה לא נדון בטיפים לגבי סוגים, אבל חשוב לנו לוודא שאתם מודעים לקיומם אם תשמעו עליהם או תראו אותם בשימוש.
שמות המשתנים
מאחר שלמשתני Python אין סוג שמופיע בקוד המקור, מומלץ לתת למשתנים שמות משמעותיים כדי להזכיר לעצמכם מה קורה. לכן, צריך להשתמש ב-'name' אם מדובר בשם יחיד, ב-'names' אם מדובר ברשימת שמות וב-'tuples' אם מדובר ברשימת צמדי ערך-מאפיין. הרבה שגיאות בסיסיות ב-Python נובעות מהשכחה של סוג הערך בכל משתנה, לכן כדאי להשתמש בשמות המשתנים (כל מה שיש לכם באמת) כדי לשמור על הסדר.
לגבי שמות בפועל, בשפות מסוימות עדיפים שמות משתנים שמכילים "יותר ממילה אחת" עם קו תחתון, אבל בשפות אחרות עדיפים שמות עם אותיות רישיות (camelCasing). באופן כללי, ב-Python מעדיפים את השיטה של קו התחתון, אבל המפתחים מודרכים להשתמש בשיטת camelCasing אם הם משלבים קוד Python קיים שכבר משתמש בסגנון הזה. חשוב לשמור על קריאוּת. מידע נוסף זמין בקטע על מוסכמות למתן שמות ב-PEP 8.
כפי שאפשר לנחש, אי אפשר להשתמש במילות מפתח כמו 'if' ו-'while' כשמות של משתנים – אם תעשו זאת, תקבלו שגיאת תחביר. עם זאת, חשוב להיזהר לא להשתמש בפונקציות מובנות כשמות של משתנים. לדוגמה, השמות 'str', 'list' ו-'print' עשויים להיראות כמו שמות טובים, אבל הם יבטלו את הגדרות ברירת המחדל של משתני המערכת האלה. פונקציות מובנות הן לא מילות מפתח, ולכן מפתחים חדשים של Python עלולים להשתמש בהן בטעות.
מידע נוסף על מודולים ומרחב השמות שלהם
נניח שיש לכם מודול 'binky.py' שמכיל 'def foo()'. השם המלא של פונקציית foo הזו הוא 'binky.foo'. כך, מודולים שונים של Python יכולים לתת שמות לפי רצונם לפונקציות ולמשתנים שלהם, ושמות המשתנים לא יהיו בקונפליקט – module1.foo שונה מ-module2.foo. במילון Python, נאמר של-binky, ל-module1 ול-module2 יש "מרחבי שמות" משלהם, שהם, כפי שאפשר לנחש, קישורים של שמות משתנים לאובייקטים.
לדוגמה, יש לנו את המודול הרגיל 'sys' שמכיל כמה שירותי מערכת רגילים, כמו הרשימה argv והפונקציה exit(). באמצעות ההצהרה 'ייבוא sys' אפשר לגשת להגדרות במודול ה-sys ולהפוך אותן לזמינות לפי השם המוגדר במלואו, למשל sys.exit() . (כן, גם ל-'sys' יש מרחב שמות!)
import sys # Now can refer to sys.xxx facilities sys.exit(0)
יש טופס ייבוא נוסף שנראה כך: "from sys import argv, exit". כך אפשר להשתמש ב-argv וב-exit() בשמות המקוצרים שלהם. עם זאת, מומלץ להשתמש בטופס המקורי עם השמות המלאים, כי קל יותר לקבוע מאיפה הגיעה פונקציה או מאפיין.
יש הרבה מודולים וחבילות שכלולים בהתקנה הרגילה של מתורגם Python, כך שאין צורך לעשות שום דבר נוסף כדי להשתמש בהם. הספריות האלה נקראות ביחד 'ספריית Python הרגילה'. מודולים/חבילות נפוצים כוללים:
- sys – גישה ל-exit(), argv, stdin, stdout וכו'
- re — ביטויים רגולריים
- os — ממשק מערכת הפעלה, מערכת קבצים
המסמכים של כל המודולים והחבילות בספרייה הרגילה זמינים בכתובת http://docs.python.org/library.
עזרה אונליין, help()
ו-dir()
יש כמה דרכים לקבל עזרה בנושא Python.
- מבצעים חיפוש ב-Google שמתחיל במילה python, למשל python list או python string lowercase. לרוב, ההיט הראשון הוא התשובה. מסיבה כלשהי, נראה שהשיטה הזו עובדת טוב יותר ב-Python מאשר בשפות אחרות.
- באתר הרשמי של מסמכי העזרה של Python – docs.python.org – יש מסמכים באיכות גבוהה. עם זאת, חיפוש של כמה מילים ב-Google בדרך כלל מהיר יותר.
- יש גם רשימת תפוצה רשמית של 'מדריך' שמיועדת במיוחד למי שלא מתמצא ב-Python או בתכנות.
- הרבה שאלות (ותשובות) זמינות ב-StackOverflow וב-Quora.
- משתמשים בפונקציות help() ו-dir() (ראו בהמשך).
בתוך המפרש של Python, הפונקציה help() מפעילה מחרוזות של מסמכי עזרה למודולים, לפונקציות ולשיטות שונים. מחרוזות המסמך האלה דומות ל-Javadoc של Java. הפונקציה dir() מציינת את המאפיינים של אובייקט. ריכזנו כאן כמה דרכים לקרוא לפונקציות help() ו-dir() מהמפר interpreter:
help(len)
— מחרוזת עזרה לפונקציה המובניתlen()
. שימו לב שצריך להשתמש ב-"len" ולא ב-"len()", כי זו קריאה לפונקציה, ואנחנו לא רוצים קריאה.help(sys)
— מחרוזת עזרה למודולsys
(קודם צריך לבצעimport sys
)dir(sys)
—dir()
דומה ל-help()
, אבל הוא רק מציג רשימה מהירה של הסמלים שהוגדרו בו, או 'המאפיינים' שלוhelp(sys.exit)
– מחרוזת עזרה לפונקציהexit()
במודולsys
help('xyz'.split)
— מחרוזת עזרה של שיטתsplit()
לאובייקטים מסוג מחרוזת. אפשר להפעיל אתhelp()
עם האובייקט עצמו או עם דוגמה לאובייקט הזה, יחד עם המאפיין שלו. לדוגמה, קריאה ל-help('xyz'.split)
זהה לקריאה ל-help(str.split)
.help(list)
– מחרוזת עזרה ל-list
אובייקטיםdir(list)
– הצגת מאפייני האובייקטlist
, כולל השיטות שלוhelp(list.append)
— מחרוזת עזרה לשיטהappend()
של אובייקטים מסוגlist