Menu
Coddy logo textTech

מתודות קסם של מכלים

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Python של Coddy. שיעור 35 מתוך 64.

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

הנה דוגמה למחלקה עם מתודות קסם של מכלים:

class CustomList:
    def __init__(self, items):
        self.items = items
    
    def __len__(self):
        return len(self.items)
    
    def __getitem__(self, index):
        return self.items[index]
    
    def __setitem__(self, index, value):
        self.items[index] = value
    
    def __iter__(self):
        return iter(self.items)
    
    def __contains__(self, item):
        return item in self.items

השיטה __len__ מאפשרת ל־len() לעבוד:

my_list = CustomList([1, 2, 3, 4])
print(len(my_list))  # 4

המתודה __getitem__ מאפשרת שימוש באינדקסים לצורך שליפה:

print(my_list[2])    # 3
print(my_list[0])    # 1

המתודה __setitem__ מאפשרת להשתמש באינדקס לצורך השמה:

my_list[1] = 10
print(my_list[1])    # 10

השיטה __contains__ מאפשרת לאופרטור in לעבוד:

print(3 in my_list)     # True
print(100 in my_list)   # False

המתודה __iter__ מאפשרת איטרציה:

for item in my_list:
    print(item)

פלט:

4
3
1
10
True
False
1
10
3
4

נקודה מרכזית: מתודות קסם של מכלים כמו __len__, __getitem__, __setitem__, __iter__ ו־__contains__ גורמות למחלקות המותאמות אישית שלך להתנהג כמו מכלים מובנים. כך האובייקטים שלך תומכים באינדוקס, באיטרציה ובבדיקת חברות באופן אינטואיטיבי.

challenge icon

אתגר

בינוני

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

עליכם לערוך רק את הקובץ deck.py. פעלו לפי הערות TODO בקוד, המנחות אתכם במימוש של:

  • אתחול של חפיסה רגילה בת 52 קלפים (באמצעות מחרוזות כמו "2H", "KD", "AS")
  • תמיכה בפעולות המובנות של Python:
    • גישה לפי אינדקס (deck[0])
    • בדיקת אורך (len(deck))
    • איטרציה (for card in deck)
    • בדיקת חברות ("AS" in deck)
  • מתודת shuffle לערבוב סדר הקלפים באופן אקראי

נסו בעצמכם

from deck import Deck

# מנגנון מקיף לטיפול במקרי בדיקה
test_case = input()

def test_basic_functionality():
    deck = Deck()
    assert len(deck) == 52, f"Deck should have 52 cards, but has {len(deck)}"
    
    first_card = deck[0]
    assert isinstance(first_card, str), f"Card should be a string, but got {type(first_card)}"
    
    assert "AS" in deck, "Ace of Spades should be in the deck"
    assert "XY" not in deck, "XY is not a valid card and should not be in the deck"
    
    cards = [card for card in deck]
    assert len(cards) == 52, f"Iteration should yield 52 cards, but got {len(cards)}"
    
    original_first_five = [deck[i] for i in range(5)]
    deck.shuffle()
    shuffled_first_five = [deck[i] for i in range(5)]
    assert original_first_five != shuffled_first_five or len(deck) <= 5, "Shuffle should change card order"
    
    print("Basic functionality tests passed!")

def test_edge_cases():
    deck = Deck()
    
    # בדיקת הגישה לקלף הראשון ולקלף האחרון
    first_card = deck[0]
    last_card = deck[51]
    assert isinstance(first_card, str) and isinstance(last_card, str), "First and last cards should be strings"
    
    # בדיקת שימוש באינדקסים שליליים
    assert deck[-1] == deck[51], "Negative indexing should work correctly"
    
    # בדיקת גישה מחוץ לגבולות
    try:
        invalid_card = deck[52]
        print("Test failed: Should raise IndexError for out of bounds access")
    except IndexError:
        print("Edge case test passed: IndexError raised for out of bounds access")
    
    print("Edge case tests passed!")

def test_card_uniqueness():
    deck = Deck()
    cards = [card for card in deck]
    unique_cards = set(cards)
    
    assert len(unique_cards) == 52, f"All cards should be unique, but found {len(unique_cards)} unique cards"
    
    # וידוא שקלפים מסוימים קיימים
    expected_cards = ["2H", "10S", "KD", "AC"]
    for card in expected_cards:
        assert card in deck, f"Expected card {card} not found in deck"
    
    print("Card uniqueness tests passed!")

def test_shuffle_behavior():
    deck = Deck()
    original_order = [card for card in deck]
    
    # ערבוב ראשון
    deck.shuffle()
    first_shuffle = [card for card in deck]
    assert len(first_shuffle) == 52, "Shuffle should preserve all 52 cards"
    assert set(first_shuffle) == set(original_order), "Shuffle should not add or remove cards"
    
    # סביר להניח שהסדר השתנה (אם כי יש סיכוי זעיר שלא)
    different_order = (original_order != first_shuffle)
    
    # ערבוב שני ליתר ביטחון
    deck.shuffle()
    second_shuffle = [card for card in deck]
    different_order_2 = (first_shuffle != second_shuffle)
    
    assert different_order or different_order_2, "Multiple shuffles should change the order"
    
    print("Shuffle behavior tests passed!")

def test_contains_behavior():
    deck = Deck()
    
    # בדיקה שכל הקלפים התקינים נמצאים בחפיסה
    suits = ['H', 'D', 'C', 'S']
    ranks = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
    
    for suit in suits:
        for rank in ranks:
            card = rank + suit
            assert card in deck, f"Valid card {card} should be in the deck"
    
    # בדיקה שקלפים לא תקינים אינם נמצאים בחפיסה
    invalid_cards = ["1H", "11S", "XD", "AX", "JX", ""]
    for card in invalid_cards:
        assert card not in deck, f"Invalid card {card} should not be in the deck"
    
    print("Contains behavior tests passed!")

def test_iteration_behavior():
    deck = Deck()
    
    # בדיקת מעבר על הקלפים
    card_count = 0
    for card in deck:
        card_count += 1
        assert isinstance(card, str), f"Each card should be a string, but got {type(card)}"
    
    assert card_count == 52, f"Iteration should yield 52 cards, but got {card_count}"
    
    # בדיקת מעברים חוזרים על הקלפים
    first_iteration = [card for card in deck]
    second_iteration = [card for card in deck]
    assert first_iteration == second_iteration, "Multiple iterations should yield the same order"
    
    print("Iteration behavior tests passed!")

# הרץ את הבדיקה המתאימה לפי הקלט
if test_case == "basic_functionality":
    test_basic_functionality()
elif test_case == "edge_cases":
    test_edge_cases()
elif test_case == "card_uniqueness":
    test_card_uniqueness()
elif test_case == "shuffle_behavior":
    test_shuffle_behavior()
elif test_case == "contains_behavior":
    test_contains_behavior()
elif test_case == "iteration_behavior":
    test_iteration_behavior()
else:
    # בדיקת ברירת מחדל - הרץ את חבילת הבדיקות המקורית
    def test_deck():
        try:
            # בדוק את האתחול ואת האורך
            deck = Deck()
            assert len(deck) == 52, f"Deck should have 52 cards, but has {len(deck)}"
            
            # בדוק את getitem
            first_card = deck[0]
            assert isinstance(first_card, str), f"Card should be a string, but got {type(first_card)}"
            
            # בדוק את contains
            assert "AS" in deck, "Ace of Spades should be in the deck"
            assert "XY" not in deck, "XY is not a valid card and should not be in the deck"
            
            # בדיקת מעבר על הקלפים
            cards = [card for card in deck]
            assert len(cards) == 52, f"Iteration should yield 52 cards, but got {len(cards)}"
            assert len(set(cards)) == 52, "All cards in the deck should be unique"
            
            # בדוק את shuffle (בדיקה בסיסית שהסדר משתנה)
            original_first_five = [deck[i] for i in range(5)]
            deck.shuffle()
            shuffled_first_five = [deck[i] for i in range(5)]
            assert original_first_five != shuffled_first_five or len(deck) <= 5, "Shuffle should change card order"
            
            # בדוק ש-shuffle אינו מאבד קלפים
            assert len(deck) == 52, f"Deck should still have 52 cards after shuffle, but has {len(deck)}"
            
            print("All tests passed!")
        except AssertionError as e:
            print(f"Test failed: {e}")

    test_deck()
    print("Tests completed")
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר Python אונליין