Menu

האופרטורים and, or, not ב-Python: אופרטורים לוגיים, קיצור הערכה ו-Truthiness

איך עובדים האופרטורים and, or ו-not ב-Python: טבלאות אמת, ערכים truthy ו-falsy, קיצור הערכה, למה and/or מחזירים אחד מהאופרנדים, קדימות, ו-and/or לעומת & ו-|.

בדף הזה יש עורכים שאפשר להריץ - לערוך, להריץ ולראות את הפלט מיד.

שלוש מילים במקום סימנים

האופרטורים הלוגיים של Python הם המילים באנגלית and, or ו-not. בשפות אחרות כותבים אותם &&, || ו-!. ב-Python && ו-|| הם SyntaxError, ו-! מופיע רק כחלק מ-!= ("לא שווה").

עם True ו-False הכללים הם אלה שמצפים להם:

aba and ba or bnot a
TrueTrueTrueTrueFalse
TrueFalseFalseTrueFalse
FalseTrueFalseTrueTrue
FalseFalseFalseFalseTrue

and צריך ששני הצדדים יהיו אמת. or צריך לפחות אחד. not מקבל ערך יחיד והופך אותו.

בקוד אמיתי הצדדים הם בדרך כלל השוואות, והתוצאה מוזנת ל-if או ל-while:

פלט:

eligible
standard ticket

זה מספיק לרוב התנאים. שאר העמוד מסביר מה האופרטורים עושים עם ערכים שאינם True או False, ואת הכללים שקובעים איזה צד של ביטוי רץ.

ערכים truthy ו-falsy

and, or ו-not מקבלים כל ערך, לא רק ערכים בוליאניים. Python מחליטה אם ערך נחשב אמת לפי ה-truthiness שלו. הערכים האלה הם falsy:

  • False ו-None
  • אפס מכל טיפוס מספרי: 0, 0.0
  • מכולות ומחרוזות ריקות: "", [], (), {}, set(), range(0)

כל השאר truthy, כולל "0", "False", [0] ו--1. אפשר לראות איך Python מסווגת ערך בעזרת bool():

פלט:

0 False
1 True
-1 True
'' False
'0' True
[] False
[0] True
None False
0.0 False

המחרוזת "0" היא truthy כי היא מחרוזת לא ריקה. זה תופס אנשים שקוראים מספרים מהקלט ובודקים אותם לפני ההמרה. העמוד על מספרים ובוליאנים מסביר את הקשר בין bool ל-int.

and ו-or מחזירים אופרנד

כאן Python שונה מרוב השפות. and ו-or לא מייצרים True או False חדשים. הם מחזירים אחד משני הערכים שנתתם להם:

  • x or y מחזיר את x אם x הוא truthy, ואחרת מחזיר את y.
  • x and y מחזיר את x אם x הוא falsy, ואחרת מחזיר את y.

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

not הוא היוצא מן הכלל: הוא תמיד מחזיר True או False.

אם אתם צריכים ערך בוליאני אמיתי מביטוי and/or, למשל כדי לשמור אותו או להחזיר אותו מפונקציה שמבטיחה bool, עטפו אותו ב-bool():

קיצור הערכה (Short-Circuit)

Python מעריכה את and ואת or משמאל לימין ועוצרת ברגע שהתשובה ידועה:

  • and עוצר בערך ה-falsy הראשון, כי שום דבר אחריו לא יכול להפוך את כל הביטוי לאמת.
  • or עוצר בערך ה-truthy הראשון, כי שום דבר אחריו לא יכול להפוך את כל הביטוי לשקר.

הצד שדולגו עליו לא רץ בכלל. אפשר לראות את זה קורה עם פונקציות שמדפיסות כשקוראים להן:

פלט:

and:
  checking A
False
or:
  checking A
True

B אף פעם לא נבדק באף אחד מהמקרים. קיצור ההערכה הוא מה שהופך תנאי הגנה לבטוחים. החצי השני של כל תנאי למטה היה קורס לבד, אבל הוא רץ רק אחרי שהחצי הראשון שלל את המקרה הבעייתי:

שימו את הבדיקה הזולה או המגינה ראשונה. היפוך הסדר, user.startswith("admin") and user is not None, זורק AttributeError כש-user הוא None.

דפוסים שמבוססים על or ו-and

מכיוון ש-or מחזיר את האופרנד ה-truthy הראשון שלו, הוא נותן ערך ברירת מחדל בשורה אחת:

פלט:

Hello, Ada!
Hello, guest!
Hello, guest!

הבעיה היא ש-or מחליף כל ערך falsy, לא רק את None. אם 0, "" או [] הם קלט לגיטימי, or ייפטר ממנו:

השתמשו ב-x if x is not None else default כשאפס או ערך ריק הם ערך תקין. העמוד על if/else מסביר את ביטוי התנאי הזה.

ל-and יש דפוס מקביל: "השתמש בערך הזה רק אם הראשון מוגדר". הוא פחות נפוץ ולעיתים קרובות ברור יותר כ-if, אז השתמשו בו במשורה:

קדימות: not, אחריו and, ואחריו or

כשביטוי מערבב את שלושתם, Python מפעילה קודם את not, אחריו את and, ואחריו את or. השוואות כמו ==, < ו-in מופעלות לפני כולם.

a or b and c ו-(a or b) and c נותנים תשובות שונות מאותם ערכים, ולכן תנאי מעורב צריך סוגריים גם כשסדר ברירת המחדל במקרה נכון. הם לא עולים כלום ומורידים את השאלה מהקורא הבא.

and/or לעומת &/|

& ו-| נראים דומים ל-and ול-or ולפעמים נותנים אותה תשובה, אבל הם אופרטורים שונים.

  • and / or בודקים truthiness, מקצרים את ההערכה ומחזירים אחד מהאופרנדים.
  • & / | הם אופרטורים של ביטים. על מספרים שלמים הם משלבים את הביטים של שני המספרים. על sets פירושם חיתוך ואיחוד. על True ו-False הם מחזירים ערך בוליאני. הם אף פעם לא מקצרים: שני הצדדים תמיד מוערכים.

לאופרטורים של ביטים יש גם קדימות גבוהה יותר מלהשוואות, וזה הופך תנאי שנכתב עם & למשהו אחר לגמרי:

1 & y הוא 1 & 5, כלומר 1, ולכן השורה האמצעית הופכת לשרשרת 5 > 1 > 1, ו-1 > 1 שקרי. בקוד Python רגיל, השתמשו ב-and, or ו-not לתנאים.

המקום היחיד שבו &, | ו-~ נכונים לתנאים הוא NumPy ו-pandas. מערך מחזיק ערכים רבים, ולכן אין לו ערך אמת יחיד, ו-and זורק ValueError: The truth value of an array ... is ambiguous. הספריות מעמיסות את & ואת | כך שיעבדו איבר אחר איבר, ולכן סינונים ב-pandas נראים כמו df[(df.age > 18) & (df.country == "CA")], עם סוגריים סביב כל השוואה בגלל סיבת הקדימות שלמעלה.

any() ו-all(): and ו-or על רשימה

כדי לשלב רצף שלם של תנאים, השתמשו בפונקציות המובנות all() (and על כל הפריטים) ו-any() (or על כל הפריטים). שתיהן מקצרות את ההערכה באותו אופן:

בניגוד ל-and ו-or, any() ו-all() תמיד מחזירות ערך בוליאני.

טעויות נפוצות

השוואת משתנה אחד לכמה ערכים עם or. התנאי הזה תמיד אמת:

Python קוראת את התנאי הראשון כ-(color == "red") or "blue". ההשוואה היא False, ולכן or מחזיר את "blue", מחרוזת לא ריקה, שהיא truthy. חזרו על ההשוואה בשני הצדדים, או עדיף, בדקו שייכות עם in.

כתיבת && או ||. שניהם SyntaxError. השתמשו ב-and וב-or.

ציפייה לערך בוליאני מ-and/or. x = a or b שומר את a או את b עצמם. לרוב זה מה שרוצים, אבל אם פונקציה צריכה להחזיר True או False, המירו עם bool().

הסתמכות על קדימות בתנאים מעורבים. a or b and c חוקי ומוגדר היטב, אבל הוסיפו סוגריים כדי שאף אחד לא יצטרך לזכור את הכלל.

שאלות נפוצות

מה עושה האופרטור and ב-Python?

a and b אמת רק כששני הצדדים אמת. Python מעריכה קודם את a: אם a הוא falsy היא מחזירה את a בלי להסתכל על b, ואחרת היא מחזירה את b. עם ערכים בוליאניים רגילים זה נותן את התוצאה המוכרת: True and False הוא False.

למה 0 or 5 מחזיר 5 ולא True?

or ו-and מחזירים אחד מהאופרנדים שלהם, לא ערך בוליאני חדש. x or y מחזיר את x אם x הוא truthy, ואחרת את y. 0 הוא falsy, ולכן 0 or 5 מחזיר 5. עטפו את הביטוי ב-bool() אם אתם צריכים True או False אמיתי.

מה ההבדל בין and ל-& ב-Python?

and הוא אופרטור לוגי: הוא בודק truthiness ומקצר את ההערכה. & הוא אופרטור ביטים: על מספרים שלמים הוא משלב ביטים (6 & 3 הוא 2), על sets הוא מחזיר חיתוך, והוא תמיד מעריך את שני הצדדים. השתמשו ב-and בתנאי if. היוצא מן הכלל הוא NumPy ו-pandas, שבהם & הוא and ברמת האיבר.

מה רץ קודם ב-Python, and או or?

not נקשר הכי חזק, אחריו and, ואחריו or. לכן a or b and c פירושו a or (b and c), ו-not a or b פירושו (not a) or b. השוואות כמו == ו-< נקשרות חזק יותר משלושתם.

אפשר להשתמש ב-&& וב-|| ב-Python?

לא. && ו-|| הם SyntaxError ב-Python. האופרטורים הלוגיים הם המילים and, or ו-not. & או | בודדים הם תקינים, אבל פירושם משהו אחר (and/or ברמת הביטים).

איור של שפות התכנות ב-Coddy

ללמוד תכנות עם Coddy

להתחיל