הסתרת מידע
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Python של Coddy. שיעור 30 מתוך 64.
הסתרת מידע מגבילה גישה ישירה לרכיבי אובייקט ומחייבת שכל האינטראקציות יתבצעו דרך ממשקים מוגדרים היטב. כך מוגנים הנתונים הפנימיים מפני גישה לא מורשית.
הנה דוגמה למחלקה עם רמות שונות של הסתרת מידע:
class BankAccount:
def __init__(self, owner, initial_balance):
self.owner = owner # ציבורי - ניתן לגשת אליו ישירות
self._balance = initial_balance # מוגן - לשימוש פנימי
self.__account_number = "ACC123456" # פרטי - מוסתר מגישה מבחוץהוסיפו מתודות שמספקות גישה מבוקרת לנתונים מוסתרים:
class BankAccount:
def __init__(self, owner, initial_balance):
self.owner = owner
self._balance = initial_balance
self.__account_number = "ACC123456"
def deposit(self, amount):
if amount > 0:
self._balance += amount
return True
return False
def withdraw(self, amount):
if amount > 0 and amount <= self._balance:
self._balance -= amount
return True
return False
def get_balance(self):
return self._balance
def get_account_info(self):
# דרך בטוחה להציג חלק מהמידע הפרטי
return f"Owner: {self.owner}, Account: ***{self.__account_number[-4:]}"השתמשו במחלקה דרך הממשק הציבורי שלה:
account = BankAccount("Alice", 1000)גישה ישירה לנתונים ציבוריים:
print(account.owner) # Alice - גישה ציבורית תקינההשתמשו בשיטות מבוקרות לגישה לנתונים מוגנים:
print(account.get_balance()) # 1000 - גישה מבוקרת
account.deposit(500)
print(account.get_balance()) # 1500 - היתרה השתנתה באופן בטוחנסה לגשת לנתונים מוסתרים:
print(account.get_account_info()) # בעלים: Alice, חשבון: ***3456
# print(account.__account_number) # AttributeError - מוסתרהמאפיין הפרטי עובר שינוי שם, אך עדיין אפשר לגשת אליו מבחינה טכנית:
# זה עובד, אבל מפר את עקרון הסתרת המידע:
print(account._BankAccount__account_number) # ACC123456פלט:
Alice
1000
1500
Owner: Alice, Account: ***3456
ACC123456נקודה מרכזית: הסתרת מידע מגנה על נתונים פנימיים בכך שהיא הופכת אותם לפרטיים או למוגנים, ואז מספקת גישה מבוקרת באמצעות מתודות ציבוריות. כך נמנעת מניפולציה ישירה של נתונים רגישים, ומובטחת שלמות הנתונים באמצעות אימות במתודות הגישה.
אתגר
בינוניבאתגר הזה תממשו מערכת הודעות מאובטחת עם בדיקות מקיפות לאימות הפתרון שלכם.
עליכם לערוך את securemessenger.py כדי לממש את המחלקה SecureMessenger בהתאם לעקרונות הסתרת מידע. הקובץ מכיל הערות TODO מפורטות שינחו אתכם במימוש.
הדרישות העיקריות כוללות:
- כימוס נאות של פרטי הכניסה וההודעות
- אימות לפני מתן אפשרות לביצוע פעולות בהודעות
- ניטור אבטחה באמצעות מעקב אחר ניסיונות כניסה
- הודעות החזרה מדויקות כפי שמפורטות בהערות ה-TODO
נסו בעצמכם
from securemessenger import SecureMessenger
# מטפל במקרי בדיקה
test_case = input()
if test_case == "default_test":
# מקרה בדיקה סטנדרטי מהבעיה המקורית
messenger = SecureMessenger("user1")
# נסה להוסיף הודעות לפני ההתחברות
print(messenger.add_message("Hello World!"))
print(messenger.add_message("Secure Message"))
# נסה להתחבר עם סיסמה שגויה
print(messenger.login("wrong_pass"))
# התחבר עם הסיסמה הנכונה
print(messenger.login("secure123"))
# הוסף הודעות לאחר התחברות מוצלחת
print(messenger.add_message("Hello World!"))
print(messenger.add_message("Secure Message"))
# אחזר הודעות
print(messenger.get_messages())
# בדוק ניסיונות התחברות
print(messenger.get_login_attempts())
elif test_case == "custom_password":
# בדיקה עם סיסמה מותאמת אישית
messenger = SecureMessenger("admin", "admin123")
print(messenger.login("wrong_password"))
print(messenger.login("admin123"))
print(messenger.get_login_attempts())
elif test_case == "multiple_login_attempts":
# בדיקה של ניסיונות התחברות מרובים
messenger = SecureMessenger("user2")
print(messenger.login("attempt1"))
print(messenger.login("attempt2"))
print(messenger.login("attempt3"))
print(messenger.login("secure123"))
print(messenger.get_login_attempts())
elif test_case == "message_management":
# ניהול Test message
messenger = SecureMessenger("user3")
print(messenger.login("secure123"))
# הוסף כמה הודעות
messages = ["Message 1", "Message 2", "Message 3", "Message 4", "Message 5"]
for msg in messages:
print(messenger.add_message(msg))
# ודאו את כל ההודעות
print(messenger.get_messages())
elif test_case == "empty_messages":
# בדקו את המקרה של הודעות ריקות
messenger = SecureMessenger("user4")
print(messenger.login("secure123"))
print(messenger.get_messages())
elif test_case == "access_without_login":
# בדקו גישה ללא התחברות
messenger = SecureMessenger("user5")
print(messenger.add_message("Unauthorized message"))
print(messenger.get_messages())
elif test_case == "attribute_privacy":
# בדקו את פרטיות המאפיינים
messenger = SecureMessenger("user6")
# מאפיין ציבורי
print(f"Public username: {messenger.username}")
# מאפיינים פרטיים - אלה אמורים להעלות AttributeError
try:
print(messenger.__password)
except AttributeError as e:
print("Password is private: AttributeError")
try:
print(messenger.__messages)
except AttributeError as e:
print("Messages are private: AttributeError")
try:
print(messenger.__login_attempts)
except AttributeError as e:
print("Login attempts are private: AttributeError")
try:
print(messenger.__is_logged_in)
except AttributeError as e:
print("Login status is private: AttributeError")
elif test_case == "login_logout_sequence":
# בדיקה זו דורשת להרחיב את המחלקה באמצעות מתודת logout
# לצורך הבדיקה, ניצור תת־מחלקה עם יכולת logout
class ExtendedMessenger(SecureMessenger):
def logout(self):
self._SecureMessenger__is_logged_in = False
return "Logged out successfully"
messenger = ExtendedMessenger("user7")
print(messenger.login("secure123"))
print(messenger.add_message("Test message"))
print(messenger.get_messages())
print(messenger.logout())
print(messenger.get_messages())
elif test_case == "stress_test":
# בדיקת עומס עם הודעות רבות
messenger = SecureMessenger("user8")
print(messenger.login("secure123"))
# הוסיפו 100 הודעות
for i in range(1, 101):
messenger.add_message(f"Message {i}")
# ודאו את מספר ההודעות
messages = messenger.get_messages()
newline_char = '\n' # שמרו את תו ירידת השורה במשתנה
message_count = len(messages.split(newline_char))
print(f"Added 100 messages. Retrieved {message_count} messages.")השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים (OOP)
קבצים חיצונייםמבוא ל-OOPמחלקות לעומת אובייקטיםהפרמטר selfמתודותמאפייניםשיטת הבנאי (__init__)חזרה: מחשבון פשוט5פולימורפיזם
בחינה מחדש של דריסת מתודותטיפוסיות ברווזמחלקות ומתודות אבסטרקטיותעיצוב ממשקיםסיכום – מחשבון צורות8מושגים מתקדמים בתכנות מונחה עצמים
קומפוזיציה לעומת הורשהMixinsמתודות סטטיות ומתודות מחלקהדקורטורים למחלקותמנהלי הקשרתרגלו בעצמכם: קומפיילר Python אונליין