7.1 דקורטורים מתקדמים פתרון
def dataclass(cls):
"""Decorator to automatically generate special methods for a class."""
# Get the list of attributes of the class
fields = [name for name in dir(cls) if not name.startswith("__")]
# Define __init__ method
def init(self, *args, **kwargs):
for name, value in zip(fields, args):
setattr(self, name, value)
for name, value in kwargs.items():
setattr(self, name, value)
# Define __repr__ method
def repr(self):
attr_str = ', '.join(f"{name}={getattr(self, name)!r}" for name in fields)
return f"{cls.__name__}({attr_str})"
# Define __eq__ method
def eq(self, other):
if type(other) is type(self):
return all(getattr(self, name) == getattr(other, name) for name in fields)
return False
# Attach methods to the class
cls.__init__ = init
cls.__repr__ = repr
cls.__eq__ = eq
return cls
# Example usage:
@dataclass
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
# Creating objects
person1 = Person("Alice", 30)
person2 = Person("Bob", 25)
# Testing methods
print(person1) # Output: Person(name='Alice', age=30)
print(person2) # Output: Person(name='Bob', age=25)
print(person1 == person2) # Output: False
@dataclass
class Point:
x: int
y: int
# Usage
p1 = Point(3, 4)
p2 = Point(3, 4)
print(repr(p1)) # Output: Point(x=3, y=4)
print(p1 == p2) # Output: True
- שימו לב שקיימים מספר בעיות בפתרון הזה, כגון:
- כאשר אני מחשב את המשתנה fields, אני עושה dir על כל הממברים של הקלאס, ואם יש מתודה בקלאס אני קלטתי אותה במשתנה שאמור להכיל רק את השדות.
- בinit אני עושה setattr לכל משתנה שאני מקבל בkwargs, אז למעשה אני יכול להעביר איזה keyword argument שאני רוצה למחלקה וזה יצור לי את המשתנה גם אם הוא לא אמור להיות קיים במחלקה. הvalidation שבודק אם המשתנה שהועבר לי הוא בfields קורה רק בargs לא בkwargs
- בנוסף חסר פה המון פיצ'רים שיש בdataclass.
- הפתרון שהעלתי הוא פתרון פשוט יחסית, והצפייה מהתרגיל הוא פתרון שדומה לשלי, כל פתרון יותר מרוכב מקובל מבורך.