W Pythonie tworzenie obiektu klasy to proces dwuetapowy:
__new__, która odpowiada za przydzielenie i zwrócenie nowej instancji klasy.__init__, która inicjalizuje już utworzony obiekt.__new__ — tworzenie (można zwrócić dowolny nowy obiekt; obowiązkowy parametr — klasa).__init__ — inicjalizacja (pracuje z self, już przydzieloną instancją).__new__ jest przesłaniane dla dziedziczących po niemutowalnych typach (tuple, str, int), tworzenia singletonów i wzorca "fabryka".class MyStr(str): def __new__(cls, value): print("__new__ wywołane") instance = super().__new__(cls, value.upper()) # zmieniamy wartość przed utworzeniem return instance def __init__(self, value): print("__init__ wywołane", value) s = MyStr('abc') # __new__ wywołane -> __init__ wywołane abc print(s) # 'ABC'
Czy można zainicjować niemutowalny obiekt przez __init__, jeśli w klasie nie zrealizowano __new__?
Nie! Na przykład dla niemutowalnych typów (jak str, int, tuple) wszelkie zmiany nad polami/wartością muszą odbywać się w __new__, inaczej w __init__ nie można zmienić wartości.
class MyTuple(tuple): def __init__(self, items): print(f'__init__! {items}') def __new__(cls, items): print(f'__new__! {items}') return super().__new__(cls, map(str, items)) t = MyTuple([1, 2, 3]) print(t) # ('1', '2', '3')
Historia
W dużym projekcie Django zaimplementowano dziedziczenie po str do przechowywania specjalnych typów ciągów. Próbowano zmieniać wartość w __init__ — ale wynik nie zmieniał się, ponieważ str jest niemutowalny. Naprawiono to dopiero po zbadaniu i przesłonięciu __new__.
Historia
Podczas implementacji wzorca Singleton zapomniano zaimplementować logikę zwracania istniejącej instancji w __new__: kilka wywołań klasy nadal tworzyło nowe obiekty, co prowadziło do fragmentacji pamięci.
Historia
W bibliotece do serializacji danych podczas cachowania użyto klasy z przesłoniętym __init__, ale nie zauważono, że do cachowania potrzebny jest właśnie zwrot tego samego obiektu przez __new__. Z tego powodu cache psuł się przy każdym nowym wywołaniu, ponieważ tworzone były różne obiekty.