רעננו את הדף והקליקו למעבר לנושא הבא:

טיפול ב-attributes

טיפול ב-attributes

__getattr__, __setattr__ , __delattr__

לאובייקט שאנו מייצרים במחלקה ישנן attribuetes או אם תרצו, תכונות. לעיתים נרצה לטפל בתכונות הללו או ליתר דיוק באפשרות לעשות בהן שימוש או למחוק אותן מהאובייקט.


class MyAttributes: def __init__(self): self.data = {'a': 'alfa', 'b': 'beta'} def __getattr__(self, attr): return self.data[attr] obj = MyAttributes() d=obj.a print(d)

>>>

alfa

בדוגמא למעלה, אנו מעבירים במסגרת המתודה המיוחדת __init__ שורה של תכונות (attributes) בתוך מילון. תכונה a היא alfa תכונה b היא beta. כדי להגיע לתכונה מסוימת דווקא ברשימת התכונות, אנו נזקקים ל- __getattr__ ולאחר ששיבצנו את המתודה במחלקה שלנו אנו יכולים לגשת לתכונה מסוימת ולראות אותה.

כאשר אנו רוצים להוסיף באותו אופן תכונה נוספת לרשימה שלנו שתגיב ל- obj.c שעדיין לא קיימת, הדברים מעט מסתבכים, קחו אוויר, וננסה להסביר מה עושה המתודה המיוחדת __setattr__ ולמה זה יותר מסובך. פייתון משתמשת באותה שיטה כדי לבצע השמה של attribute ולכן שימוש אינטואיטיבי בפונקציה מהצורה self.data[key]=value כאשר מתודת __init__ נותרת כפי שהיא - יגרום לרקורסיה אינסופית - ()__setattr__ תקרא לעצמה....

לבעיה הזאת יש כמה פתרונות – שהבא מביניהם נראה לי יותר אלגנטי והוא גם קרוי בפייתון new style כך שאין מצב למשהו ב- old style.


class MyAttributes: def __init__(self): object.__setattr__(self,"data", {'a': 'alfa', 'b': 'beta'}) def __getattr__(self, key): return self.data[key] def __setattr__(self, key, value): self.data[key]=value def __repr__(self): return f"{self.data}" obj = MyAttributes() obj.c="cool" print(obj)

אנו קוראים למחלקה הבסיסית באמצעות ()object.__setattr__ כדי לחמוק מ- ()__setattr__

והרקורסיה הכרוכה בו.


התוצאה

{'a': 'alfa', 'b': 'beta', 'c': 'cool'}

הצלחנו לשבץ תכונה חדשה תחת השם c, זה cool. בלי לגרום לרקורסיה אינסופית.

באותו אופן גם הטיפול ב- __delattr__ עובר באופן חלק – ואנו מצליחים למחוק תכונה מהמחלקה שלנו.


class MyAttributes: def __init__(self): object.__setattr__(self,"data", {'a': 'alfa', 'b': 'beta'}) def __getattr__(self, key): return self.data[key] def __setattr__(self, key, value): self.data[key]=value def __delattr__(self, key): del self.data[key] def __repr__(self): return f"{self.data}" obj = MyAttributes() obj.c="cool" del obj.a print(obj)

הנה, מחקנו attribute

התוצאה

{'b': 'beta', 'c': 'cool'}