tuple ו-set — רשומה קבועה ואוסף בלי כפילויות

מטרות השיעור
  • ליצור tuple, לגשת לאיבריו ולפרק אותו למשתנים (Unpacking)
  • להסביר למה tuple לא ניתן לשינוי ומתי זה יתרון
  • ליצור set, להוסיף ולמחוק איברים ולהסיר כפילויות מרשימה
  • לבצע פעולות קבוצות — איחוד, חיתוך והפרש

מה נלמד?

שני מבני נתונים נוספים, כל אחד עם “כוח-על” משלו:

  • tuple — כמו רשימה, אבל קבוע: אי אפשר לשנות אותו אחרי היצירה.
  • set — אוסף בלי כפילויות ובלי סדר, שמאפשר בדיקה מהירה מאוד אם ערך קיים בו.

למה צריך את זה?

  • tuple מתאים לנתונים שמייצגים רשומה אחת עם מבנה קבוע: נקודה (x, y), תאריך (2026, 10, 6), שורה מ-Database (7, "Dana", 24). בנושא Backend ומסדי נתונים, כל שורה שתחזור מה-Database תגיע כ-tuple! הקביעות מבטיחה שאף קוד לא ישנה “בטעות” רשומה.
  • set מתאים כשרוצים ייחודיות: כמה משתמשים שונים ביקרו באתר היום? אילו תגיות יש לפוסט? מי רשום לשני קורסים גם יחד?

הסבר מהבסיס

tuple

tuple הוא רצף מסודר של ערכים, שלא ניתן לשינוי (Immutable). אחרי שנוצר, אי אפשר להוסיף, למחוק או להחליף איברים.

  • נכתב בסוגריים עגולים: (1, 2, 3).
  • גישה לאיברים כמו ברשימה: point[0], point[-1], len(point), in.
  • אין append, remove, ואין השמה לאיבר.

Unpacking (פירוק): אפשר “לפרק” tuple ישר למשתנים:

student = ("Dana", 24, "Haifa")
name, age, city = student

כבר השתמשנו בזה בלי לשים לב: for name, age in attempts: ו-for position, name in enumerate(...).

אנלוגיה

list היא כמו רשימת קניות על לוח מחיק: מוסיפים, מוחקים, משנים. tuple הוא כמו תאריך לידה בתעודת זהות: מודפס פעם אחת, ואף אחד לא אמור לשנות אותו.

set

set הוא אוסף של ערכים ייחודיים:

  • בלי כפילויות — הוספה של ערך שכבר קיים לא עושה כלום.
  • בלי סדר — אין אינדקסים. my_set[0] הוא שגיאה. הסדר בהדפסה יכול להיות כל סדר.
  • ניתן לשינוי — אפשר להוסיף ולמחוק.
  • בדיקת in מהירה מאוד, גם עם מיליון איברים. ברשימה, in עובר איבר-איבר.
  • נכתב בסוגריים מסולסלים: {1, 2, 3}. אבל set ריק נוצר עם set(), כי {} הוא dict ריק (השיעור הבא).

פעולות קבוצות

פעולהאופרטורמשמעות
איחוד (Union)a | bכל מה שנמצא ב-a או ב-b
חיתוך (Intersection)a & bמה שנמצא גם ב-a וגם ב-b
הפרש (Difference)a - bמה שב-a ולא ב-b

תחביר

# tuple
point = (3, 5)
single = (7,)              # a tuple with ONE item needs a comma!
x, y = point               # unpacking
point[0]                   # 3

# set
tags = {"python", "web"}
empty_set = set()          # NOT {} - that is an empty dict
tags.add("api")            # add one item
tags.remove("web")         # remove (KeyError if missing)
tags.discard("xyz")        # remove if present, no error if missing
"python" in tags           # fast membership test
unique = set([1, 1, 2])    # {1, 2} - remove duplicates from a list

a | b    # union
a & b    # intersection
a - b    # difference

דוגמת קוד ראשונה

week-2/tuples_demo.py:

student = ("Dana", 24, "Haifa")

print("Full record:", student)
print("Name:", student[0])
print("Fields:", len(student))

name, age, city = student
print(name, "is", age, "and lives in", city)

student[1] = 25

פלט:

Full record: ('Dana', 24, 'Haifa')
Name: Dana
Fields: 3
Dana is 24 and lives in Haifa
Traceback (most recent call last):
  File "tuples_demo.py", line 10, in <module>
    student[1] = 25
TypeError: 'tuple' object does not support item assignment

פירוק הקוד שורה אחר שורה

שורההסבר
student = ("Dana", 24, "Haifa")tuple עם 3 שדות. המיקום קובע את המשמעות: 0 = שם, 1 = גיל, 2 = עיר.
student[0]גישה כמו ברשימה.
name, age, city = studentUnpacking: האיבר הראשון נכנס ל-name, השני ל-age, השלישי ל-city. מספר המשתנים חייב להיות שווה למספר האיברים.
student[1] = 25ניסיון לשנות, ונזרק TypeError. זו לא תקלה, זו ההגנה שה-tuple נותן.

רוצים “לשנות” tuple? יוצרים חדש: student = (student[0], 25, student[2]).

דוגמה נוספת

ניתוח משתמשים באתר עם set. week-2/visitors.py:

monday_visits = ["dana", "avi", "dana", "noa", "avi", "dana"]
tuesday_visits = ["noa", "yossi", "rina", "noa"]

monday = set(monday_visits)
tuesday = set(tuesday_visits)

print("Monday page views:", len(monday_visits))
print("Monday unique visitors:", len(monday), monday)

print("Visited on both days:", monday & tuesday)
print("Visited on any day:", monday | tuesday)
print("Only on Monday:", monday - tuesday)

tuesday.add("dana")
tuesday.add("noa")
print("Tuesday after adds:", len(tuesday), "unique")
print("Did yossi visit on Monday?", "yossi" in monday)

פלט (סדר האיברים בתוך {} יכול להיות שונה אצלכם):

Monday page views: 6
Monday unique visitors: 3 {'avi', 'noa', 'dana'}
Visited on both days: {'noa'}
Visited on any day: {'dana', 'yossi', 'rina', 'avi', 'noa'}
Only on Monday: {'avi', 'dana'}
Tuesday after adds: 4 unique
Did yossi visit on Monday? False

פירוק:

  • set(monday_visits) — ממיר רשימה ל-set, והכפילויות נעלמות: 6 צפיות, 3 מבקרים.
  • monday & tuesday — חיתוך: רק מי שמופיע בשניהם (noa).
  • monday | tuesday — איחוד: כל מי שביקר, כל אחד פעם אחת.
  • monday - tuesday — הפרש: ביקרו ביום שני ולא ביום שלישי.
  • tuesday.add("noa") — noa כבר קיימת, ולכן לא קורה כלום. נוספה רק dana, ויש 4 (noa, yossi, rina, dana).

מתי מה? טבלת השוואה

listtupleset
כתיבה[1, 2](1, 2){1, 2}
סדר / אינדקס✓✓✗
שינוי✓✗✓
כפילויות✓✓✗
שימוש טיפוסיאוסף שגדל ומשתנהרשומה עם מבנה קבועייחודיות ובדיקת שייכות

טעות נפוצה

הטעות 1: tuple של איבר אחד בלי פסיק.

colors = ("red")
print(type(colors))
<class 'str'>

סוגריים לבד הם רק סוגריים של חשבון, כמו (2 + 3). כדי ליצור tuple של איבר אחד: ("red",). הפסיק יוצר את ה-tuple, לא הסוגריים.

הטעות 2: {} כ-set ריק.

seen = {}
seen.add("dana")
AttributeError: 'dict' object has no attribute 'add'

{} הוא dict ריק. set ריק = set().

הטעות 3: לצפות לסדר או לאינדקס ב-set.

names = {"dana", "avi"}
print(names[0])
TypeError: 'set' object is not subscriptable

ל-set אין “ראשון”. אם צריך סדר, ממירים לרשימה ממוינת: sorted(names).

הטעות 4: Unpacking עם מספר משתנים לא תואם.

name, age = ("Dana", 24, "Haifa")
ValueError: too many values to unpack (expected 2)

תרגול

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

תרגיל 1: Unpacking

student = ("Dana", 24, "Haifa")

פרקו את ה-tuple לשלושה משתנים בשורה אחת, והדפיסו משפט עליהם. אחר כך נסו לשנות את הגיל ל-25 — מה קורה?

פלט צפוי:

Dana is 24 and lives in Haifa
הצג פתרון
student = ("Dana", 24, "Haifa")

name, age, city = student
print(name, "is", age, "and lives in", city)
Dana is 24 and lives in Haifa

student[1] = 25 יזרוק TypeError: 'tuple' object does not support item assignment — tuple הוא Immutable. אם צריך לשנות, יוצרים tuple חדש: student = (name, 25, city).

תרגיל 2: פונקציה שמחזירה שני ערכים

כתבו פונקציה min_max(numbers) שמחזירה tuple של הקטן והגדול ביותר. פרקו את התוצאה לשני משתנים.

lowest, highest = min_max([40, 3, 99, 17])
print(lowest, highest)

פלט צפוי:

3 99
הצג פתרון
def min_max(numbers):
    return (min(numbers), max(numbers))


lowest, highest = min_max([40, 3, 99, 17])
print(lowest, highest)
3 99

פונקציה מחזירה תמיד ערך אחד — כאן tuple. ה-Unpacking בצד של הקורא הופך אותו לשני משתנים.

תרגיל 3: מבקרים ייחודיים

visits = ["dana", "avi", "dana", "noa", "avi", "dana"]

הדפיסו כמה צפיות היו, כמה מבקרים שונים היו, ואם "tom" ביקר.

פלט צפוי:

6 views
3 visitors
False
הצג פתרון
visits = ["dana", "avi", "dana", "noa", "avi", "dana"]

unique = set(visits)
print(len(visits), "views")
print(len(unique), "visitors")
print("tom" in unique)
6 views
3 visitors
False

set לא מחזיק כפילויות, ולכן len(set(...)) סופר כמה ערכים שונים יש. בדיקת in על set גם מהירה מאוד.

תרגיל 4: פעולות קבוצות

football = {"dana", "avi", "noa", "tom"}
chess = {"noa", "rina", "tom", "yossi"}
  1. מי בשני החוגים?
  2. מי רק בכדורגל?
  3. כמה ילדים שונים יש בסך הכול?

הדפיסו את התשובות 1 ו-2 ממוינות, כדי שהסדר יהיה קבוע.

פלט צפוי:

['noa', 'tom']
['avi', 'dana']
6
הצג פתרון
football = {"dana", "avi", "noa", "tom"}
chess = {"noa", "rina", "tom", "yossi"}

print(sorted(football & chess))
print(sorted(football - chess))
print(len(football | chess))
['noa', 'tom']
['avi', 'dana']
6
  • & — חיתוך (בשתיהן). - — הפרש (רק בראשונה). | — איחוד (באחת מהן לפחות).
  • ל-set אין סדר קבוע, ולכן sorted מחזיר רשימה ממוינת להדפסה.

תרגיל 5: list, tuple או set?

לכל מקרה — באיזה מבנה הייתם משתמשים? הסבירו.

  1. קואורדינטות של נקודה על מפה: רוחב ואורך.
  2. רשימת משימות שמוסיפים לה ומוחקים ממנה, לפי סדר.
  3. כתובות האימייל של כל מי שנרשם — בלי כפילויות.
  4. התור בקופה בסופרמרקט.
הצג פתרון
  1. tuple — רשומה קבועה של שני ערכים שלא אמורים להשתנות: (32.08, 34.78).
  2. list — סדר חשוב, ומוסיפים ומוחקים.
  3. set — בלי כפילויות, ובדיקה מהירה אם כתובת כבר קיימת.
  4. list — הסדר חשוב, ושולפים מההתחלה (pop(0)).

סיכום

  • tuple ( , ) — מסודר, לא ניתן לשינוי. מתאים לרשומה עם מבנה קבוע. איבר אחד: (x,).
  • Unpacking: a, b = (1, 2). ככה מחזירים ומקבלים כמה ערכים מפונקציה.
  • set { } — בלי כפילויות, בלי סדר, בלי אינדקס. set ריק = set().
  • set(list) מסיר כפילויות. in על set מהיר מאוד.
  • פעולות קבוצות: | איחוד, & חיתוך, - הפרש.
  • בנושא Backend ומסדי נתונים, שורות מ-Database יחזרו כ-tuple.

דוקומנטציה רשמית