5.4 אנקפסולציה הרצאה
ממברים פרטיים _¶
- ממברים פרטיים (private members) הם ממברים שאתה לא יכול לגשת אליהם.
- בפייתון כל ממבר ששמו מתחיל עם
_הוא מוגדר כממבר פרטי. - הנה דוגמה למחלקה עם ממבר פרטי
class Player: def __init__(self, speed): self.name = name self.speed = speed self._position_x = 0 # A private member def walk_forward(self): self._position_x += self.speed self._print_location() def _print_location(self): # A private member print(f"* player in {self._position_x} location") # Good code - accessing only public membera p = Player(speed=3) p.walk_forward() print(p.speed) # Bad code - accessing private members print(p._position_x) p._print_location() - אפשר לראות שהממברים
_position_xו -_print_locationהם ממברים פרטיים, ו -walk_forwardו -speedהם ממברים רגילים (ציבוריים). - מחוץ למחלקה אנחנו נגשים רק לממברים ציבוריים, אנחנו נגשים לממברים פרטיים רק בתוך המחלקה.
- לא כמו שפות תכנות אחרות, פייתון לא פוקד עלייך חוסר גישה לממברים פרטיים מחוץ למחלקה אבל עדיין לעשות את זה נחשב קוד לא נכון, אז לא לעשות את זה כמו בדוגמה למעלה.
- השימוש ב
_בשמות כדי לצור ממברים פרטיים הוא קונבנציה, זה הדרך שלנו כמתכנתים להודיע על ממבר שלא אמורים לגשת אילו מבחוץ. - פייתון סומך על המפתחים שלו שיעקבו אחרי קונבנציות כמו אלו.
אנקפסולציה - Encapsulation¶
- מה אם נרצה לגשת לממבר הפרטי מחוץ למחלקה מסיבה כלשהי?
- אנקפסולציה: אנחנו יכולים לצור פונקציות שמטרתן להביא גישה לממברים פרטיים.
class MyClass: def __init__(self): self._private_variable = 42 def get_private_variable(self): # Getter method return self._private_variable def set_private_variable(self, value) # Setter method if value != 0 raise ValueError("Value cannot be zero!") self._private_variable = value # Outside the class obj = MyClass() # Accessing private member through a public method (following convention) print(obj.get_private_variable()) obj.set_private_variable(5) print(obj.get_private_variable()) - למה? לפעמים אנחנו רוצים לתת למתכנת גישה למשתנה הפרטי שלנו פשוט עם הגבלות מסויימות, ניתן לעשות את זה עם עטיפות של מתודות שאנחנו כותבים.
- מתודת get (getter) - מתודה שמאפשרת גישה לערך של ממבר פרטי.
- מתודת set (setter) - מתודה שמאפשרת גישה לשנות את הערך של ממבר פרטי.
- ניתן לראות בדוגמה למעלה שיש לנו משתנה פרטי בשם
_private_variableואנחנו מאפשרים גישה חופשית לערך שלו באמצעות getter, ומאפשרים גישה לערוך אותו כל עוד לא נותנים לו את הערך 0, באמצעות setter.
פרופרטי - Property decorator¶
- דרך פייתונית לעשות getter ו - setter זה באמצעות הדקורטור property
class TemperatureConverter: def __init__(self, celsius): self._celsius = celsius @property def celsius(self): return self._celsius @celsius.setter def celsius(self, value): if value < -273.15: raise ValueError("Temperature cannot be below absolute zero.") self._celsius = value @property def fahrenheit(self): return (self._celsius * 9/5) + 32 temperature = TemperatureConverter(25) temperature.celsius = 30 # Using the setter method print(f"Celsius: {temperature.celsius}") print(f"Fahrenheit: {temperature.fahrenheit}") - עם property גם אפשר להגדיר getter ו- setter בצורה יותר יפה, וגם המתכנת יכול לגשת לממבר הפרטי כיאלו הוא ציבורי במקום לקרוא לפונקציות של getter ו - setter. ממש קסם!
דאטה קלאס - Dataclass¶
- בפייתון המון פעמים אנחנו נרצה לכתוב מחלקה שרק שומרת מידע כמו זו:
class Point: def __init__(self, x, y): self.x = x self.y = y def __repr__(self): return f"Point(x={self.x}, y={self.y})" def __eq__(self, other): if not isinstance(other, Point): return False return self.x == other.x and self.y == other.y # Example usage p1 = Point(1, 2) p2 = Point(1, 2) print(p1 == p2) # Automatically compares attributes for equality print(p1) - זה לא כיף ויעיל לכתוב כל כך הרבה קוד רק כדי לשמור מידע, בשביל זה יש לנו דאטה קלאס!
- דאטה קלאס זה דקורטור שאפשר להוסיף לקלאס שלנו כדי לצור קלאסים ששומרים מידע בפשטות יותר
- דאטה קלאסים אוטמטית יוצרים את כל הmagic methods שצריך כדי לצור מחלקה פשוטה ששומרת מידע.
- שימו לב: אפשר לראות שהגדרנו קלאס ששומרת שדות סטטים, אבל זה לא באמת יהיו שדות סטטים זה פשוט איך שמגדירים דאטה קלאס.
- נקודה חשובה: יש עוד המון פיצ'רים לdataclass שלא הצגתי, מוזמנים לקרוא עליהם בתיעוד של dataclass באינטרנט - הצגתי רק את הפיצ'רים היותר חשובים.