איברים ציבוריים, מוגנים ופרטיים
חלק מהיחידה תכנות מונחה עצמים במסלול ה-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 מבוססת על מוסכמות ואינה נאכפת בקפדנות.
אתגר
בינוניבאתגר הזה תממשו מחלקה BankAccount שמדגימה שימוש נכון ברמות גישה ציבורית, מוגנת ופרטית ב-Python.
bankaccount.py- מכיל את הגדרת המחלקה עם הערות TODO שמנחות אתכם במימוש
- פעלו לפי הערות TODO ב-
bankaccount.pyכדי לממש את הפונקציונליות הנדרשת - ממשו רמות גישה מתאימות (ציבורית, מוגנת, פרטית) כפי שצוין
- ודאו שכל המתודות מטפלות כראוי במקרי קצה (הפקדות שליליות וכו׳)
נסו בעצמכם
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}")
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים (OOP)
קבצים חיצונייםמבוא ל-OOPמחלקות לעומת אובייקטיםהפרמטר selfמתודותמאפייניםשיטת הבנאי (__init__)חזרה: מחשבון פשוט5פולימורפיזם
בחינה מחדש של דריסת מתודותטיפוסיות ברווזמחלקות ומתודות אבסטרקטיותעיצוב ממשקיםסיכום – מחשבון צורות8מושגים מתקדמים בתכנות מונחה עצמים
קומפוזיציה לעומת הורשהMixinsמתודות סטטיות ומתודות מחלקהדקורטורים למחלקותמנהלי הקשר6כימוס
איברים ציבוריים, מוגנים ופרטייםמשני גישההסתרת מידעדקורטורים מתקדמים של Propertyחזרה - מערכת רישומי תלמידים12פרויקט: ניהול ספרייה
סקירת הפרויקטמחלקות ספר ומשתמשמערכת השאלת ספריםיכולת חיפושממשק מנהלבדיקות ואינטגרציהתרגלו בעצמכם: קומפיילר Python אונליין