מבוא ל-Python

הקדמה

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

אם אתם מחפשים קורס נלווה בנושא MOOC, כדאי לנסות את הקורסים של Udacity ו-Coursera (מבוא לתכנות [למתחילים] או מבוא ל-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.", הדוגמאות האלה אמורות להתאים לכם.

כפי שאפשר לראות למעלה, קל להתנסות עם משתנים ואופרטורים. בנוסף, המתרגם מציג, או 'מעלה', בשפת Python, שגיאה בתחילת ההפעלה אם הקוד מנסה לקרוא משתנה שלא הוקצה לו ערך. כמו 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 דרכים שונות לחזרה על מחרוזות באמצעות האופרטור'+' שהוא ידידותי יותר למשתמש, אבל * פועל גם כי הוא האופרטור "חזרה" של Python. כלומר, '-' * 10 מספק ל-'----------' דרך מסודרת ליצור "שורה" במסך. בתגובת הקוד, רמזנו ש- * פועל מהר יותר מ-+, הסיבה לכך ש-* מחשב את גודל האובייקט שנוצר פעם אחת, בעוד שעם +, החישוב מתבצע בכל פעם שנקרא +. גם האופרטורים + וגם * נקראים אופרטורים "עומס יתר" כי יש להם משמעות שונה למספרים לעומת מחרוזות (וסוגי נתונים אחרים).

מילת המפתח def מגדירה את הפונקציה עם פרמטרים בתוך סוגריים והקוד שלה עם כניסת פיסקה. השורה הראשונה של פונקציה יכולה להיות מחרוזת תיעוד ("docstring") שמתארת את הפעולה של הפונקציה. ה-docstring יכול להיות שורה אחת, או תיאור עם כמה שורות כמו בדוגמה שלמעלה. (כן, אלה "ציטוטים משולשים", תכונה ייחודית ל-Python!) משתנים שמוגדרים בפונקציה צריכים להיות מקומיים לאותה פונקציה, כך ש'תוצאה' בפונקציה שלמעלה נפרדת ממשתנה 'תוצאה' בפונקציה אחרת. ההצהרה return יכולה לקבל ארגומנט. במקרה כזה, הערך שמוחזר למבצע הקריאה החוזרת.

לפניכם קוד שקורא לפונקציה חזרה() שלמעלה, ומדפיס את מה שהיא מחזירה:

def main():
    print(repeat('Yay', False))      ## YayYayYay
    print(repeat('Woo Hoo', True))   ## Woo HooWoo HooWoo Hoo!!!

בזמן הריצה, הפונקציות חייבות להיות מוגדרות באמצעות הרצה של 'def' לפני שמפעילים אותן. ברוב המקרים, מסיימים פונקציה ראשית (()) לקראת סוף הקובץ עם הפונקציות שהיא קוראת מעליה.

כניסת פסקה

אחת מהתכונות המיוחדות של Python היא שכניסת רווח לבן בקטע קוד משפיעה על המשמעות שלו. קבוצה לוגית של הצהרות, כמו אלה שמהן מורכב הפונקציה, צריכה לכלול את אותה כניסה, שמוכנסת מהכניסה של פונקציית ההורה, או 'if' או משהו אחר. אם באחת השורות בקבוצה יש כניסת פיסקה שונה, היא מסומנת כשגיאת תחביר.

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

שאלה נפוצה שאנשים מתחילים שואלים היא "כמה רווחים צריך להוסיף לכניסת פיסקה?" לפי מדריך הסגנון הרשמי של Python (PEP 8), צריך להוסיף 4 רווחים לכניסת פיסקה. (עובדה מעניינת: הנחיית הסגנון הפנימי של Google מכתיבה כניסת פיסקה בשני רווחים!)

הקוד נבדק בזמן הריצה

Python עושה מעט מאוד בדיקה בזמן ההידור, ודוחה כמעט כל בדיקה של סוג, שם וכו' בכל שורה עד שהשורה הזו תפעל. נניח שהקריאות הראשיות () שלמעלה חוזרות על עצמן, כך:

def main():
    if name == 'Guido':
        print(repeeeet(name) + '!!!')
    else:
        print(repeat(name))

ה-if-statement מכיל שגיאה ברורה, שבה הפונקציה return() מוקלדת בטעות כ-repeeeet(). הקטע המצחיק ב-Python ... הקוד הזה מהדר ופועל בצורה תקינה כל עוד השם בזמן הריצה הוא לא 'Guido'. רק כאשר ריצה מנסה להפעיל את repeeeet() , המערכת תזהה שאין פונקציה כזו ותוצג הודעת שגיאה. יש גם שגיאה שנייה בקטע הקוד הזה. לא הוקצה ערך לפני ההשוואה ל-'Guido'. אם תנסו להעריך משתנה שלא הוקצה, שפת Python תעלה 'NameError'. אלה כמה דוגמאות שממחישות שכאשר מפעילים לראשונה תוכנה של Python, חלק מהשגיאות הראשונות שיופיעו יהיו שגיאות הקלדה פשוטות או משתנים לא מאותחלים כמו אלה. מדובר בתחום שבו יש יתרון לשפות עם מערכת טיפוסים מורכבת יותר, כמו Java ... הן יכולות לאתר שגיאות כאלה בזמן ההידור (אבל כמובן שצריך לשמור את כל הפרטים האלה ... אפשר להתפשר).

ב-Python 3 נוספו טיפים לסוגי תוכן. הינטים לטיפוסים מאפשרים לציין את הסוג של כל ארגומנט בפונקציה, וכן את הסוג של האובייקט שהפונקציה מחזירה. למשל, בפונקציה המבוארת def is_positive(n: int) -> bool:, הארגומנט n הוא int והערך המוחזר הוא bool. בהמשך נדון במשמעות של הסוגים האלה. עם זאת, הרמזים של טיפוסים הם אופציונליים לחלוטין. יותר ויותר קודים מתבססים על רמזים, כי כשמשתמשים בהם, חלק מהעורכים, כמו cider-v ו-VS.code יכולים להריץ בדיקות כדי לוודא שהפונקציות נקראות עם סוגי הארגומנטים הנכונים. הם אפילו יכולים להציע ולאמת ארגומנטים בזמן שאתם עורכים את הקוד. המדריך הזה לא יעסוק ברמזים מסוגים שונים, אבל חשוב לנו להיות מודעים להם אם שמעתם עליהם או שתראו אותם בטבע.

שמות משתנים

מכיוון שלמשתני Python אין סוג כלשהו מאוית בקוד המקור, רצוי לתת שמות משמעותיים למשתנים כדי להזכיר לכם מה קורה. לכן, יש להשתמש ב-"name" אם מדובר בשם יחיד, וב-"names" אם זו רשימה של שמות, וב-"tuples" אם מדובר ברשימת שמות. הרבה שגיאות בסיסיות ב-Python נובעות מכך ששכחתם מהו סוג הערך בכל משתנה. לכן, חשוב להשתמש בשמות המשתנים (כל מה שיש לכם בפועל) כדי לשמור על דיוק.

בכל הקשור למתן שמות בפועל, שפות מסוימות מעדיפות שימוש בחלקי קו תחתון בשמות של משתנים המורכבים מ "יותר ממילה אחת", אך שפות אחרות מעדיפות שימוש ב-CalCasing. באופן כללי, שפת Python מעדיפה את שיטת הקו התחתון, אבל היא מנחה את המפתחים להימנע משימוש ב-CalCasing אם הם משתלבים בקוד Python קיים שכבר משתמש בסגנון הזה. ספירת קריאות. מידע נוסף זמין בקטע בנושא מוסכמות מתן שמות ב-PEP 8.

כפי שאתם יכולים לנחש, לא ניתן להשתמש במילות מפתח כמו 'if' ו-'while' בתור שמות משתנים - אם תעשו זאת, תקבלו שגיאת תחביר. עם זאת, הקפידו לא להשתמש במילות מפתח מובנות בתור שמות משתנים. לדוגמה, אמנם השמות 'str', 'list' ו-'print' עשויים להיראות כמו שמות טובים, אבל אז משתני המערכת האלה יוחלפו. אפליקציות מובנות הן לא מילות מפתח, ולכן מפתחי Python חדשים עלולים להשתמש בהם בטעות.

מידע נוסף על מודולים ומרחבי השמות שלהם

נניח שיש לך מודול "binky.py" שמכיל "def foo() ". השם המלא של הפונקציה ב-foo הוא "binky.foo". באופן כזה, מודולים שונים של Python יכולים לתת לפונקציות ולמשתנים שלהם כל שם שתרצו, ושמות המשתנים לא יתנגשו — מודול1.foo שונה מ-Module2.foo. באוצר המילים של Python, נניח של-Bbinky, ב-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 מאשר בשפות אחרות מסיבה כלשהי.
  • אתר מסמכי Python הרשמי - docs.python.org - כולל מסמכים באיכות גבוהה. עם זאת, לעתים קרובות אני מוצא שחיפוש Google שכולל שתי מילים הוא מהיר יותר.
  • יש גם רשימת תפוצה רשמית של מדריכים שנועדה במיוחד למשתמשים חדשים ב-Python ו/או בתכנות!
  • אפשר למצוא שאלות (ותשובות) רבות ב-StackOverflow וב-Quora.
  • משתמשים בפונקציות help() ו-dir() (ראו בהמשך).

בתוך רכיב התרגום של Python, פונקציית help() מקבלת מחרוזות תיעוד עבור מודולים, פונקציות ושיטות שונות. מחרוזות המסמכים האלה דומות ל-Javadoc של Java. הפונקציה dir() מציינת את התכונות של אובייקט. בהמשך מפורטות כמה דרכים לקרוא ל-help() ול-dir() מהמפענח:

  • help(len) – מחרוזת עזרה של פונקציית len() המובנית. חשוב לשים לב ש-Lens ולא 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 אובייקטים