מחרוזות Python

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

מחרוזות Python הן 'לא ניתנות לשינוי', ולכן לא ניתן לשנות אותן לאחר שהן נוצרות (גם מחרוזות Java משתמשות בסגנון הזה שאינו ניתן לשינוי). מכיוון שלא ניתן לשנות מחרוזות, אנחנו יוצרים מחרוזות *חדשות* כאשר אנחנו מייצגים ערכים מחושבים. לדוגמה, הביטוי ('hello' + 'there') לוקח את שתי המחרוזות 'hello' ו-'there' ויוצר מחרוזת חדשה 'hellothere'.

ניתן לגשת לתווים במחרוזת באמצעות התחביר הרגיל [ ], וכמו Java ו-C++ , שפת Python משתמשת בהוספה לאינדקס ללא בסיס, כך שאם s הוא 'hello', [1] הוא 'e'. אם האינדקס נמצא מחוץ לתחום עבור המחרוזת, Python מעלה שגיאה. הסגנון של Python (בניגוד ל-Perl) נעצר אם אין לו אפשרות לדעת מה לעשות, במקום להמציא ערך ברירת מחדל. התחביר השימושי 'slice' (בהמשך) פועל גם לחילוץ כל מחרוזת משנה ממחרוזת. הפונקציה len(string) מחזירה את האורך של מחרוזת. התחביר [ ] והפונקציה len() פועלים בפועל בכל סוג רצף - מחרוזות, רשימות וכו'. Python מנסה לגרום לפעולות שלו לפעול באופן עקבי בסוגים שונים. למתחילים ב-Python: אל תשתמשו ב-len כשם משתנה כדי לא לחסום את הפונקציה len() . האופרטור '+' יכול לשרשר שתי מחרוזות. שימו לב בקוד שבהמשך שהמשתנים אינם מוצהרים מראש – פשוט מקצים להם וממשיכים.

  s = 'hi'
  print(s[1])          ## i
  print(len(s))        ## 2
  print(s + ' there')  ## hi there

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

  pi = 3.14
  ##text = 'The value of pi is ' + pi      ## NO, does not work
  text = 'The value of pi is '  + str(pi)  ## yes

במספרים, האופרטורים הרגילים, +, /, * פועלים כרגיל. אמנם אין אופרטור ++, אך +=, -= וכו' עובדים. אם רוצים לבצע חילוק במספרים שלמים, צריך להשתמש בשני קווים נטויים. לדוגמה: 6 // 5 הוא 1

לרוב, הפונקציה 'הדפסה' מדפיסה פריט python אחד או יותר ואחריו שורה חדשה. לפני ליטרל מחרוזת "גולמי" מופיע r והוא מעביר את כל התווים ללא טיפול מיוחד בלוכסנים הפוכים. ל-"print" יכולים להיות כמה ארגומנטים כדי לשנות את האופן שבו פריטים מודפסים (ראו הגדרת פונקציית ההדפסה python.org), כמו הגדרת "end" ל-"" כדי שלא ידפיסו יותר שורה חדשה אחרי שהיא מסתיימת בהדפסת כל הפריטים.

  raw = r'this\t\n and that'

  # this\t\n and that
  print(raw)

  multi = """It was the best of times.
  It was the worst of times."""

  # It was the best of times.
  #   It was the worst of times.
  print(multi)

שיטות מחרוזת

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

  • s.lower(), s.upper() -- מחזירה את הגרסה באותיות קטנות או באותיות רישיות של המחרוזת
  • s.strip() -- מחזירה מחרוזת ללא רווח לבן שמסירים אותה מההתחלה ועד הסוף
  • s.isalpha()/s.isdigital()/s.isspace()... -- בודק אם כל תווי המחרוזת נמצאים במחלקות התווים השונות
  • s.startswith('other'), s.endswith('other') -- בודקת אם המחרוזת מתחילה או מסתיימת במחרוזת האחרת הנתונה
  • s.find('other') -- מחפש את המחרוזת האחרת הנתונה (לא ביטוי רגולרי) בתוך s, ומחזירה את האינדקס הראשון שבו היא מתחילה או -1 אם לא נמצא
  • s.replace('old', 'new') -- מחזירה מחרוזת שבה כל המופעים של 'old' הוחלפו ב-'new'
  • s.split('delim') -- מחזירה רשימה של מחרוזות משנה המופרדות על ידי התו המפריד הנתון. התו המפריד אינו ביטוי רגולרי, אלא רק טקסט. 'aaa,bbb,ccc'.split(',') -> ['aaa', 'bbb', 'ccc']. דוגמה נוחה לתרחיש מיוחד s.split() (ללא ארגומנטים) מתפצלת על כל תווים של רווח לבן.
  • s.join(list) – ההפוכה ל-Split() , מאחדת את הרכיבים ברשימה הנתונה באמצעות המחרוזת כמפריד. למשל, '---'.join(['aaa', 'bbb', 'ccc']) -> aaa---bbb---ccccc

חיפוש Google של "python str" אמור להוביל אותך אל שיטות המחרוזת הרשמיות של python.org, שמפרטות את כל שיטות str.

ל-Python אין סוג תו נפרד. במקום זאת, ביטוי כמו s[8] מחזיר מחרוזת-length-1 שמכילה את התו. באמצעות המחרוזת הזו-length-1, האופרטורים ==, <=, ... פועלים כצפוי, כך שלמעשה לא צריך לדעת של-Python אין סוג "char" נפרד סקלרי.

פרוסות מחרוזות

התחביר "פרוסה" הוא דרך נוחה להתייחס לחלקי משנה של רצפים – בדרך כלל מחרוזות ורשימות. הקטע s[start:end] הוא הרכיבים שמתחילים בהתחלה ומתרחבים עד לסוף, אבל לא כוללים אותם. נניח שיש לנו s = "שלום"

המחרוזת &#39;שלום&#39; עם אינדקסים של אותיות 0 1 2 3 4

  • s[1:4] הוא 'ell' – תווים שמתחילים באינדקס 1 ונמשכים עד אינדקס 4, אבל לא כולל
  • s[1:] הוא 'ello' – אם אחד מהאינדקס יושמט כברירת מחדל בתור התחלה או בסוף של המחרוזת
  • s[:] הוא 'שלום' – השמטת שניהם תמיד נותנת לנו עותק של הכול (זו הדרך הפיתונית להעתיק רצף כמו מחרוזת או רשימה)
  • s[1:100] הוא 'ello' -- אינדקס גדול מדי נקטע לאורך המחרוזת

מספרי אינדקס סטנדרטיים המבוססים על אפס מעניקים גישה קלה לתווים בסמוך לתחילת המחרוזת. כחלופה, Python משתמש במספרים שליליים כדי לספק גישה קלה לתווים בסוף המחרוזת: s[-1] הוא התו האחרון 'o', s[-2] הוא 'l' הוא התו הבא אחרי המחרוזת, וכן הלאה. מספרי אינדקס שליליים נספרים בסוף המחרוזת:

  • s[-1] הוא 'o' – התו האחרון (הראשון מהסוף)
  • s[-4] הוא 'e' – הרביעי מהסוף
  • s[:-3] הוא 'הוא' -- עולה לשלושת התווים האחרונים, אבל לא כולל.
  • s[-3:] הוא 'llo' – מתחיל בתו השלישי מהסוף ועד לסוף המחרוזת.

מדובר במשולשים מגניבים לכל אינדקס n, s[:n] + s[n:] == s. היא פועלת גם עבור N שליליים או מחוץ לגבולות. לחלופין, הוסיפו דרך אחרת s[:n] ו-s[n:] לבצע חלוקה למחיצות של המחרוזת לשני חלקי מחרוזות באופן אחר, תוך שימור כל התווים. כפי שנראה בהמשך בקטע הרשימה, חלקים יכולים לעבוד גם עם רשימות.

עיצוב מחרוזות

אחד הדברים המגניבים ש-python יכול לעשות הוא להמיר אובייקטים באופן אוטומטי למחרוזת שמתאימה להדפסה. לשם כך, יש שתי דרכים מובנות לעשות זאת: ליטרל מחרוזת בפורמט, שנקרא גם f-strings, ושימוש בפונקציה str.format().

ליטרלים של מחרוזת מעוצבים

לעתים קרובות יופיעו ליטרלים של מחרוזת בפורמט המתאים במצבים כמו:

  value = 2.791514
  print(f'approximate value = {value:.2f}')  # approximate value = 2.79

  car = {'tires':4, 'doors':2}
  print(f'car = {car}') # car = {'tires': 4, 'doors': 2}

התחילית של מחרוזת מילולית מעוצבת היא 'f' (לדוגמה, התחילית 'r' שמשמשת למחרוזות גולמיות). כל טקסט מחוץ לסוגריים המסולסלים '{}' מודפס ישירות. הביטויים שמופיעים ב-'{}' מודפסים באמצעות מפרט הפורמט המתואר במפרט הפורמט.יש הרבה דברים מגניבים שאפשר לעשות עם העיצוב, כולל חיתוך והמרה לסימון מדעי, ויישור לשמאל/ימין/מרכז.

ו-f-string שימושי מאוד כאשר רוצים להדפיס טבלה של אובייקטים ורוצים שהעמודות שמייצגות מאפייני אובייקטים שונים יהיו מיושרים, כמו

  address_book = [{'name':'N.X.', 'addr':'15 Jones St', 'bonus': 70},
      {'name':'J.P.', 'addr':'1005 5th St', 'bonus': 400},
      {'name':'A.A.', 'addr':'200001 Bdwy', 'bonus': 5},]

  for person in address_book:
    print(f'{person["name"]:8} || {person["addr"]:20} || {person["bonus"]:>5}')

  # N.X.     || 15 Jones St          ||    70
  # J.P.     || 1005 5th St          ||   400
  # A.A.     || 200001 Bdwy          ||     5

% מחרוזת

ב-Python יש גם מתקן ישן יותר דמוי framef() ליצירת מחרוזת. האופרטור % לוקח מחרוזת של תבנית מסוג Printf משמאל (%d int, מחרוזת %s, נקודה צפה %f/%g), ואת הערכים התואמים ב-tuple בצד ימין (משולש מורכב מערכים שמופרדים בפסיקים, ובדרך כלל מקובצים בתוך סוגריים):

  # % operator
  text = "%d little pigs come out, or I'll %s, and I'll %s, and I'll blow your %s down." % (3, 'huff', 'puff', 'house')

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

  # Add parentheses to make the long line work:
  text = (
    "%d little pigs come out, or I'll %s, and I'll %s, and I'll blow your %s down."
    % (3, 'huff', 'puff', 'house'))

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

  # Split the line into chunks, which are concatenated automatically by Python
  text = (
    "%d little pigs come out, "
    "or I'll %s, and I'll %s, "
    "and I'll blow your %s down."
    % (3, 'huff', 'puff', 'house'))

מחרוזות (Unicode לעומת בייטים)

מחרוזות Python רגילות הן Unicode.

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

> byte_string = b'A byte string'
> byte_string
  b'A byte string'

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

כדי להמיר מחרוזת Python רגילה לבייטים, צריך לקרוא ל-method encode() במחרוזת. בכיוון השני, השיטה decode() של מחרוזת בייט ממירה בייטים מקודדים פשוטים למחרוזת Unicode:

> ustring = 'A unicode \u018e string \xf1'
> b = ustring.encode('utf-8')
> b
b'A unicode \xc6\x8e string \xc3\xb1'  ## bytes of utf-8 encoding. Note the b-prefix.
> t = b.decode('utf-8')                ## Convert bytes back to a unicode string
> t == ustring                         ## It's the same as the original, yay!

True

בקטע של קריאת קבצים, יש דוגמה שמראה איך לפתוח קובץ טקסט עם קידוד מסוים ולהקריא מחרוזות Unicode.

אם ההצהרה

ב-Python לא משתמשים ב-{ } כדי לתחום בלוקים של קוד עבור if/loops/function וכו'. במקום זאת, ב-Python נעשה שימוש בנקודתיים (:) ובכניסת הפיסקה/ברווח הלבן כדי לקבץ הצהרות. הבדיקה הבוליאנית של if לא צריכה להיות בסוגריים (הבדל גדול מ-C++/Java), והיא יכולה לכלול קטעי *elif* ו-*else* (זכר: המילה "elif" זהה לאורך המילה "else").

כל ערך יכול לשמש כ-if-test. כל ערכי "אפס" נחשבים כ-false: ללא, 0, מחרוזת ריקה, רשימה ריקה, מילון ריק. יש גם סוג בוליאני עם שני ערכים: True ו-False (כשממירים אותו למספר int, הערכים האלה הם 1 ו-0). ב-Python יש את פעולות ההשוואה הרגילות: ==, !=, <, <=, >, >=. בניגוד ל-Java ו-C, == עמוס מדי כדי לעבוד כראוי עם מחרוזות. האופרטורים הבוליאניים הם המילים המאויתות *and*, *or*, *not* (ב-Python אין שימוש בסגנון C-style && || !). כך יכול להיראות הקוד של אפליקציית בריאות שמספקת המלצות לגבי משקאות במהלך היום – שימו לב איך כל בלוק של הצהרות 'אז/אחר' מתחיל ב-: וההצהרות מקובצות לפי הכניסה שלהן:

  if time_hour >= 0 and time_hour <= 24:
    print('Suggesting a drink option...')
    if mood == 'sleepy' and time_hour < 10:
      print('coffee')
    elif mood == 'thirsty' or time_hour < 2:
      print('lemonade')
    else:
      print('water')

לדעתי, השמטת ":" היא שגיאת התחביר הנפוצה ביותר בהקלדה של קוד מהסוג שלמעלה, כנראה מכיוון שזה דבר נוסף שכדאי להקליד לעומת הרגלי C++/Java. בנוסף, אל תכניסו את הבדיקה הבוליאנית לסוגריים – זה הרגל ב-C/Java. אם הקוד קצר, ניתן להוסיף את הקוד באותה שורה אחרי ":" כך (הדבר נכון גם לגבי פונקציות, לולאות וכו'), למרות שיש אנשים שמרגישים שקל יותר לרווח את הדברים בשורות נפרדות.

  if time_hour < 10: print('coffee')
  else: print('water')

תרגיל: string1.py

כדי לתרגל את החומר בקטע הזה, נסו את התרגיל string1.py בתרגילים הבסיסיים.