Menu
Coddy logo textTech

איברים ציבוריים, מוגנים ופרטיים

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

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

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

class BankAccount:
    def __init__(self, owner, balance, account_id):
        self.owner = owner           # ציבורי - נגיש מכל מקום
        self._balance = balance      # מוגן - לשימוש פנימי
        self.__account_id = account_id  # פרטי - למחלקה בלבד
    
    def deposit(self, amount):       # מתודה ציבורית
        self._balance += amount
    
    def _calculate_interest(self):   # מתודה מוגנת
        return self._balance * 0.02
    
    def __validate_transaction(self, amount):  # מתודה פרטית
        return amount > 0 and amount <= self._balance

אפשר לגשת לחברים ציבוריים מכל מקום:

account = BankAccount("Alice", 1000, "12345")
print(account.owner)        # Alice
account.deposit(500)        # עובד כראוי

גישה לחברים מוגנים (קו תחתון יחיד — מוסכמה בלבד):

print(account._balance)     # 1500 - עובד אך לא מומלץ
result = account._calculate_interest()  # עובד אך לא מומלץ
print(result)               # 30.0

נסה לגשת לחברים פרטיים (שני קווים תחתונים — השם עבר שינוי):

# זה לא יעבוד:
# print(account.__account_id)  # AttributeError

# אבל זה כן עובד (שיבוש שמות):
print(account._BankAccount__account_id)  # 12345

צרו מחלקת משנה כדי להציג את ההבדל בין גישה מוגנת לפרטית:

class SavingsAccount(BankAccount):
    def show_balance(self):
        return self._balance        # מוגן - נגיש במחלקה יורשת
    
    def show_id(self):
        # return self.__account_id  # זה לא יעבוד - פרטי
        return "Cannot access private member"
savings = SavingsAccount("Bob", 2000, "67890")
print(savings.show_balance())  # 2000
print(savings.show_id())       # לא ניתן לגשת לאיבר פרטי

פלט:

Alice
30.0
12345
2000
Cannot access private member

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

challenge icon

אתגר

בינוני

באתגר הזה תממשו מחלקה BankAccount שמדגימה שימוש נכון ברמות גישה ציבורית, מוגנת ופרטית ב-Python.

  • bankaccount.py - מכיל את הגדרת המחלקה עם הערות TODO שמנחות אתכם במימוש
  1. פעלו לפי הערות TODO ב-bankaccount.py כדי לממש את הפונקציונליות הנדרשת
  2. ממשו רמות גישה מתאימות (ציבורית, מוגנת, פרטית) כפי שצוין
  3. ודאו שכל המתודות מטפלות כראוי במקרי קצה (הפקדות שליליות וכו׳)

נסו בעצמכם

from bank_account import BankAccount

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

if test_case == "basic_test":
    # בדיקת פונקציונליות בסיסית
    account = BankAccount("John Doe", "12345")
    print(account.account_holder)  # תכונה ציבורית
    print(account.deposit(100))    # מתודה ציבורית
    print(account.get_balance())   # מתודה ציבורית

elif test_case == "transaction_count":
    # בדיקת תכונה מוגנת
    account = BankAccount("Jane Smith", "67890")
    account.deposit(50)
    account.deposit(100)
    account.deposit(200)
    print(account._transaction_count)  # תכונה מוגנת
    print(account.get_balance())

elif test_case == "invalid_deposit":
    # בדיקת אימות במתודה deposit
    account = BankAccount("Bob Johnson", "54321")
    print(account.deposit(-50))  # אמור להחזיר None
    print(account.deposit(0))    # אמור להחזיר None
    print(account.deposit(75))   # אמור להחזיר 75
    print(account.get_balance())

elif test_case == "private_access":
    # בדיקת גישה לתכונה פרטית
    account = BankAccount("Alice Brown", "98765")
    try:
        print(account.__balance)  # פעולה זו תגרום להעלאת AttributeError
    except AttributeError:
        pass
    
    try:
        print(account.__account_number)  # פעולה זו תגרום להעלאת AttributeError
    except AttributeError:
        pass
    
    print("Private attributes are not directly accessible")
    account.deposit(500)
    print(account.get_balance())  # גישה דרך מתודה ציבורית

elif test_case == "name_mangling":
    # הדגמת שינוי שמות של תכונות פרטיות
    account = BankAccount("Charlie Green", "13579")
    print(account._BankAccount__balance)        # גישה לתכונה פרטית באמצעות שינוי שמות
    print(account._BankAccount__account_number)  # גישה לתכונה פרטית באמצעות שינוי שמות
    account.deposit(300)
    print(account._BankAccount__balance)  # אמור להציג את היתרה המעודכנת

elif test_case == "multiple_accounts":
    # בדיקת חשבונות מרובים
    account1 = BankAccount("David White", "24680")
    account2 = BankAccount("Eva Black", "86420")
    account3 = BankAccount("Frank Red", "97531")
    
    account1.deposit(150)
    account2.deposit(250)
    account2.deposit(50)
    account3.deposit(500)
    account3.deposit(300)
    account3.deposit(200)
    
    print(f"{account1.account_holder}: {account1.get_balance()}")
    print(f"{account2.account_holder}: {account2.get_balance()}")
    print(f"{account3.account_holder}: {account3.get_balance()}")
    
    print(f"Account 1 transactions: {account1._transaction_count}")
    print(f"Account 2 transactions: {account2._transaction_count}")
    print(f"Account 3 transactions: {account3._transaction_count}")

elif test_case == "stress_test":
    # בדיקת ביצועים עם עסקאות רבות
    account = BankAccount("Stress Tester", "11111")
    for _ in range(1000):
        account.deposit(1)
    print(f"Final balance: {account.get_balance()}")
    print(f"Transaction count: {account._transaction_count}")
quiz iconבחנו את עצמכם

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

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

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