Что такое Dunder/Magic Methods?
Методы Dunder — это имена, которым предшествуют и за которыми следуют двойные символы подчеркивания, отсюда и название dunder. Их также называют магическими методами, и они могут помочь переопределить функциональность встроенных функций для пользовательских классов.
Описание объектов:
До:
class Data: def __init__(self, value: int): self.value = value if __name__ == '__main__': data = Data(10) print(data) # Output # <__main__.Data object at 0x7f81101a5790>
После:
class Data: def __init__(self, value: int): self.value = value def __repr__(self): return f"Data value is: {self.value}" if __name__ == '__main__': data = Data(10) print(data) # Output # Data value is: 10
Добавление или добавление двух объектов
До:
class Data: def __init__(self, value: int): self.value = value if __name__ == '__main__': data1 = Data(10) data2 = Data(20) print(data1 + data2) # Output # print(data1 + data2) # TypeError: unsupported operand type(s) for +: 'Data' and 'Data'
После:
class Data: def __init__(self, value: int): self.value = value def __add__(self, other): return self.value + other.value def __sub__(self, other): return self.value - other.value def __mul__(self, other): return self.value * other.value if __name__ == '__main__': data1 = Data(10) data2 = Data(20) print("Add") print(data1 + data2) print("Sub") print(data1 - data2) print("Mul") print(data1 * data2) # Output # Add # 30 # Sub # -10 # Mul # 200
Сравнение объектов:
До:
class Data: def __init__(self, value: int): self.value = value if __name__ == '__main__': data1 = Data(10) data2 = Data(20) print(data1 > data2) # Output # print(data1 > data2) # TypeError: '>' not supported between instances of 'Data' and 'Data'
После:
class Data: def __init__(self, value: int): self.value = value def __gt__(self, other): print("Greater Than Equal") return self.value >= other.value def __ge__(self, other): print("Greater Than") return self.value > other.value def __le__(self, other): print("Less Than Equal") return self.value <= other.value def __lt__(self, other): print("Less Than ") return self.value < other.value def __eq__(self, other): print("Equals") return self.value == other.value if __name__ == '__main__': data1 = Data(10) data2 = Data(20) print(data1 > data2) print(data1 < data2) print(data1 >= data2) print(data1 <= data2) print(data1 == data2) # Output # Greater Than Equal # False # Less Than # True # Greater Than # False # Less Than Equal # True # Equals # False
Объект как ключ в Dict и удаление повторяющихся объектов в наборе
До:
class Data: def __init__(self, value: int): self.value = value def __repr__(self): return f"Data value is - {self.value}" if __name__ == '__main__': data1 = Data(10) data2 = Data(20) date3 = Data(10) di = {data1: 10, data2: 20, date3: 10} se = {data1, data2, date3} print("Dict Value") print(di) print("Set Value") print(se) # Output # Dict Value # {Data value is - 10: 10, Data value is - 20: 20, Data value is - 10: 10} # Set Value # {Data value is - 20, Data value is - 10, Data value is - 10}
После:
class Data: def __init__(self, value: int): self.value = value def __repr__(self): return f"Data value is - {self.value}" def __hash__(self): return hash(self.value) def __eq__(self, other): return self.value == other.value if __name__ == '__main__': data1 = Data(10) data2 = Data(20) date3 = Data(10) di = {data1: 10, data2: 20, date3: 10} se = {data1, data2, date3} print("Dict Value") print(di) print("Set Value") print(se) # Output # Dict Value # {Data value is - 10: 10, Data value is - 20: 20} # Set Value # {Data value is - 10, Data value is - 20}
Сортировка объектов:
До:
class Data: def __init__(self, value: int): self.value = value def __repr__(self): return f"{self.value}" if __name__ == '__main__': data1 = Data(10) data2 = Data(20) date3 = Data(10) li = [data1, data2, date3] li.sort() print(li) # Output # li.sort() # TypeError: '<' not supported between instances of 'Data' and 'Data'
После:
class Data: def __init__(self, value: int): self.value = value def __repr__(self): return f"{self.value}" def __lt__(self, other): return self.value < other.value if __name__ == '__main__': data1 = Data(10) data2 = Data(20) date3 = Data(10) li = [data1, data2, date3] print("Before sorting") print(li) li.sort() print("After sorting") print(li) # Output # Before sorting # [10, 20, 10] # After sorting # [10, 10, 20]
Итерация объектов:
До:
class Data: def __init__(self, stream: list): self.stream = stream if __name__ == '__main__': data_stream = Data([1, 2, 3, 4]) for data_s in data_stream: print(data_s) # Output # for data_s in data_stream: # TypeError: 'Data' object is not iterable
После:
class Data: def __init__(self, stream: list): self.stream = stream self.current = 0 def __iter__(self): return self def __next__(self): if self.current >= len(self.stream): raise StopIteration value = self.stream[self.current] self.current += 1 return value if __name__ == '__main__': data_stream = Data([1, 2, 3, 4]) for data_s in data_stream: print(data_s) # Output # 1 # 2 # 3 # 4
Подробнее см. здесь.
Лучшие практики Python, нажмите здесь.
Принципы SOLID в питоне, нажмите здесь.