Chcę znać różnicę między __init__
i __call__
metod.
Na przykład:
class test:
def __init__(self):
self.a = 10
def __call__(self):
b = 20
Pierwszy służy do inicjalizacji nowo utworzonego obiektu i odbiera argumenty użyte do tego:
class Foo:
def __init__(self, a, b, c):
# ...
x = Foo(1, 2, 3) # __init__
Drugi implementuje operator wywołania funkcji.
class Foo:
def __call__(self, a, b, c):
# ...
x = Foo()
x(1, 2, 3) # __call__
__init__
metoda jest używana, gdy klasa jest wywoływana w celu zainicjowania instancji, podczas gdy__call__
metoda jest wywoływana, gdy instancja jest wywoływana__call__
?Zdefiniowanie niestandardowej
__call__()
metody w meta-klasie pozwala na wywołanie instancji klasy jako funkcji, nie zawsze modyfikując samą instancję.źródło
__call__
nie tylko pozwala na użycie instancji jako funkcji ... definiuje ciało funkcji, które jest wykonywane, gdy instancja jest używana jako funkcja.W Pythonie funkcje są pierwszorzędnymi obiektami, co oznacza: odwołania do funkcji mogą być przekazywane w danych wejściowych do innych funkcji i / lub metod i wykonywane z ich wnętrza.
Instancje klas (zwane też obiektami) można traktować tak, jakby były funkcjami: przekaż je innym metodom / funkcjom i wywołaj je. Aby to osiągnąć,
__call__
funkcja klasy musi być wyspecjalizowana.def __call__(self, [args ...])
Jako dane wejściowe przyjmuje zmienną liczbę argumentów. Zakładanie,x
że jest instancją klasyX
,x.__call__(1, 2)
jest analogiczne do wywołaniax(1,2)
lub samej instancji jako funkcji .W Pythonie
__init__()
jest poprawnie zdefiniowany jako Class Constructor (podobnie jak__del__()
Class Destructor). Dlatego istnieje wyraźne rozróżnienie między__init__()
i__call__()
: pierwszy buduje instancję klasy w górę, drugi sprawia, że taka instancja jest wywoływalna jako funkcja bez wpływu na cykl życia samego obiektu (tj.__call__
nie wpływałaby na cykl życia Nie ma wpływu na cykl budowy / zniszczenia), ale może modyfikować swój stan wewnętrzny (jak pokazano poniżej).Przykład.
źródło
def __call__
po prostudef update
, dajemy klasieupdate
metodę, która robi to samo. Może teraz również modyfikować stan wewnętrzny, jeśli zostanie wywołany poniżej jakos.update(7, 8)
. Czy to zatem__call__
tylko cukier syntactix?__call__
umożliwia wywołanie klasy. Dlaczego byłoby to wymagane?Technicznie
__init__
jest wywoływany raz,__new__
kiedy obiekt jest tworzony, aby można go było zainicjować.Ale istnieje wiele scenariuszy, w których możesz chcieć ponownie zdefiniować swój obiekt, powiedzieć, że skończyłeś z tym obiektem i może okazać się potrzebny nowy obiekt. Za pomocą
__call__
możesz ponownie zdefiniować ten sam obiekt, jakby był nowy.To tylko jeden przypadek, może być ich znacznie więcej.
źródło
źródło
__init__
byłby traktowany jako Konstruktor, gdzie jako__call__
metody można wywoływać obiekty dowolną liczbę razy. Obie__init__
i__call__
funkcje przyjmują domyślne argumenty.źródło
__init__
nie jest funkcją konstruktora, ale__new__
jest.__init__
nazywa się zaraz po__new__
__new__
tworzy instancję klasy i przyjmuje klasę jako argument, podczas gdy__init__
jest konstruktorem instancji i dlatego ją otrzymujeself
. Łatwym sposobem na sprawdzenie tego jest wywołaniea = Foo(1,2,3)
funkcji, która otrzyma argumenty konstruktora__init__
.Spróbuję to wyjaśnić na przykładzie, załóżmy, że chcesz wydrukować określoną liczbę terminów z serii Fibonacciego. Pamiętaj, że pierwsze 2 terminy serii Fibonacciego to 1. Np .: 1, 1, 2, 3, 5, 8, 13 ....
Chcesz, aby lista zawierająca liczby Fibonacciego była inicjowana tylko raz, a następnie powinna zostać zaktualizowana. Teraz możemy korzystać z
__call__
funkcjonalności. Przeczytaj odpowiedź @mudit verma. To tak, jakbyś chciał, aby obiekt był wywoływalny jako funkcja, ale nie był inicjowany przy każdym wywołaniu.Na przykład:
Dane wyjściowe to:
Jeśli zauważysz, że dane wyjściowe
__init__
zostały wywołane tylko raz, to wtedy klasa została utworzona po raz pierwszy, później obiekt został wywołany bez ponownej inicjalizacji.źródło
Możesz także użyć
__call__
metody na rzecz implementacji dekoratorów .Ten przykład pochodzi z wzorców, przepisów i idiomów języka Python 3
Wyjście :
źródło
Jest więc
__init__
wywoływany, gdy tworzysz instancję dowolnej klasy i inicjujesz również zmienną instancji.Przykład:
I
__call__
jest wywoływany, gdy wywołujesz obiekt jak każdą inną funkcję.Przykład:
źródło
__init__
jest specjalną metodą w klasach Python, jest to metoda konstruktora dla klasy. Jest wywoływany za każdym razem, gdy budowany jest obiekt klasy lub można powiedzieć, że inicjuje nowy obiekt. Przykład:Jeśli użyjemy A (), wygeneruje błąd,
TypeError: __init__() missing 1 required positional argument: 'a'
ponieważ wymaga 1 argumentu za
powodu__init__
.........
__call__
po zaimplementowaniu w klasie pomaga nam wywoływać instancję klasy jako wywołanie funkcji.Przykład:
Tutaj, jeśli użyjemy B (), działa dobrze, ponieważ nie ma tu żadnej
__init__
funkcji.źródło
__call__
pozwala na zwrócenie dowolnych wartości, podczas gdy__init__
będąc konstruktorem pośrednio zwraca instancję klasy. Jak słusznie wskazano inne odpowiedzi,__init__
wywoływany jest tylko raz, podczas gdy można wywoływać__call__
wiele razy, na wypadek, gdyby zainicjowana instancja została przypisana do zmiennej pośredniej.źródło
Krótkie i słodkie odpowiedzi są już podane powyżej. Chcę zapewnić praktyczne wdrożenie w porównaniu z Javą.
Uwaga : scenariusz 1 i scenariusz 2 wydają się takie same pod względem wyników. Ale w scenariuszu 1 ponownie tworzymy kolejną nową instancję instancji1 . W scenariuszu 2 po prostu modyfikujemy już utworzoną instancję1 .
__call__
jest tutaj korzystne, ponieważ system nie musi tworzyć nowej instancji.Odpowiednik w Javie
źródło
Możemy użyć metody call , aby użyć innych metod klasowych jako metod statycznych.
źródło