772 Stimmen

Was ist der Unterschied zwischen __init__ und __call__?

Ich möchte den Unterschied kennen zwischen __init__ et __call__ Methoden.

Zum Beispiel:

class test:

  def __init__(self):
    self.a = 10

  def __call__(self): 
    b = 20

6voto

HoangYell Punkte 2873

Fall 1:

class Example:
    def __init__(self, a, b, c):
        self.a=a
        self.b=b
        self.c=c
        print("init", self.a, self.b, self.c)

Laufen:

Example(1,2,3)(7,8,9)

Ergebnis:

- init 1 2 3
- TypeError: 'Example' object is not callable

Fall 2:

class Example:
    def __init__(self, a, b, c):
        self.a=a
        self.b=b
        self.c=c
        print("init", self.a, self.b, self.c)
    def __call__(self, x, y, z):
        self.x=x
        self.y=y
        self.z=z
        print("call", self.x, self.y, self.z)

Laufen:

Example(1,2,3)(7,8,9)

Ergebnis:

- init 1 2 3
- call 7 8 9

4voto

Uddhav P. Gautam Punkte 6634

Kurze und knappe Antworten sind bereits oben gegeben worden. Ich möchte eine praktische Umsetzung im Vergleich zu Java anbieten.

 class test(object):
        def __init__(self, a, b, c):
            self.a = a
            self.b = b
            self.c = c
        def __call__(self, a, b, c):
            self.a = a
            self.b = b
            self.c = c

    instance1 = test(1, 2, 3)
    print(instance1.a) #prints 1

    #scenario 1
    #creating new instance instance1
    #instance1 = test(13, 3, 4)
    #print(instance1.a) #prints 13

    #scenario 2
    #modifying the already created instance **instance1**
    instance1(13,3,4)
    print(instance1.a)#prints 13

Note Szenario 1 und Szenario 2 scheinen in Bezug auf das Ergebnis gleich zu sein. Aber in Szenario 1 erstellen wir wieder eine neue Instanz Instanz1 . In Szenario2, ändern wir einfach bereits erstellte Instanz1 . __call__ ist hier von Vorteil, da das System keine neue Instanz erstellen muss.

Äquivalent in Java

public class Test {

    public static void main(String[] args) {
        Test.TestInnerClass testInnerClass = new Test(). new TestInnerClass(1, 2, 3);
        System.out.println(testInnerClass.a);

        //creating new instance **testInnerClass**
        testInnerClass = new Test().new TestInnerClass(13, 3, 4);
        System.out.println(testInnerClass.a);

        //modifying already created instance **testInnerClass**
        testInnerClass.a = 5;
        testInnerClass.b = 14;
        testInnerClass.c = 23;

        //in python, above three lines is done by testInnerClass(5, 14, 23). For this, we must define __call__ method

    }

    class TestInnerClass /* non-static inner class */{

        private int a, b,c;

        TestInnerClass(int a, int b, int c) {
            this.a = a;
            this.b = b;
            this.c = c;
        }
    }
}

3voto

__init__() kann:

  • die Instanz der Klasse initialisieren.
  • viele Male angerufen werden.
  • nur Rückkehr None .

__call__() kann wie eine Instanzmethode frei verwendet werden.

Zum Beispiel, Person Klasse hat __init__() et __call__() wie unten dargestellt:

class Person:
    def __init__(self, f_name, l_name):
        self.f_name = f_name
        self.l_name = l_name
        print('"__init__()" is called.')

    def __call__(self, arg):
        return arg + self.f_name + " " + self.l_name

Jetzt erstellen und initialisieren wir die Instanz von Person Klasse wie unten gezeigt:

    # Here
obj = Person("John", "Smith")

Dann, __init__() wird wie unten dargestellt aufgerufen:

"__init__()" is called.

Als nächstes rufen wir __call__() auf 2 Arten (siehe unten):

obj = Person("John", "Smith")
print(obj("Hello, ")) # Here
print(obj.__call__("Hello, ")) # Here

Dann, __call__() wird wie unten dargestellt aufgerufen:

"__init__()" is called.
Hello, John Smith # Here
Hello, John Smith # Here

Und, __init__() kann wie unten gezeigt mehrmals aufgerufen werden:

obj = Person("John", "Smith")
print(obj.__init__("Tom", "Brown")) # Here
print(obj("Hello, "))
print(obj.__call__("Hello, "))

Dann, __init__() aufgerufen wird und die Instanz von Person Klasse reinitialisiert wird und None wird zurückgegeben von __init__() wie unten dargestellt:

"__init__()" is called.
"__init__()" is called. # Here
None # Here
Hello, Tom Brown
Hello, Tom Brown

Und, wenn __init__() kehrt nicht zurück None und wir nennen __init__() wie unten dargestellt:

class Person:
    def __init__(self, f_name, l_name):
        self.f_name = f_name
        self.l_name = l_name
        print('"__init__()" is called.')
        return "Hello" # Here

    # ...

obj = Person("John", "Smith") # Here

Der folgende Fehler tritt auf:

TypeError: __init__() sollte None zurückgeben, nicht 'str'

Und, wenn __call__ ist nicht definiert in Person Klasse:

class Person:
    def __init__(self, f_name, l_name):
        self.f_name = f_name
        self.l_name = l_name
        print('"__init__()" is called.')

    # def __call__(self, arg):
    #     return arg + self.f_name + " " + self.l_name

Dann rufen wir obj("Hello, ") wie unten dargestellt:

obj = Person("John", "Smith")
obj("Hello, ") # Here

Der folgende Fehler tritt auf:

TypeError: Objekt 'Person' ist nicht aufrufbar

Andererseits nennen wir obj.__call__("Hello, ") wie unten dargestellt:

obj = Person("John", "Smith")
obj.__call__("Hello, ") # Here

Der folgende Fehler tritt auf:

AttributeError: Objekt 'Person' hat kein Attribut '__call__'

2voto

Abhishek Jain Punkte 39

Wir können verwenden aufrufen Methode, um andere Klassenmethoden als statische Methoden zu verwenden.

class _Callable:
    def __init__(self, anycallable):
        self.__call__ = anycallable

class Model:

    def get_instance(conn, table_name):

        """ do something"""

    get_instance = _Callable(get_instance)

provs_fac = Model.get_instance(connection, "users")

2voto

Federico Baù Punkte 3486

Ich möchte einige Abkürzungen und Syntaxzucker sowie einige Techniken aufzeigen, die verwendet werden können, aber ich habe sie in den aktuellen Antworten nicht gesehen.

Instanziieren Sie die Klasse und rufen Sie sie sofort auf

In vielen Fällen, z.B. wenn eine APi-Anfrage gestellt werden soll und die Logik in einer Klasse gekapselt ist und wir eigentlich nur die Daten an diese Klasse übergeben und sie sofort als separate Entität ausführen wollen, wird die Klasse instantiate nicht benötigt. Das ist die

instance = MyClass() # instanciation
instance() # run the instance.__call__()
# now instance is not needed 

Stattdessen können wir etwas Ähnliches tun.

class HTTPApi:

    def __init__(self, val1, val2):
        self.val1 = val1
        self.val2 = val2

    def __call__(self, *args, **kwargs):
        return self.run(args, kwargs)

    def run(self, *args, **kwargs):
        print("hello", self.val1, self.val2, args, kwargs)

if __name__ == '__main__':
    # Create a class, and call it
    (HTTPApi("Value1", "Value2"))("world", 12, 213, 324, k1="one", k2="two")

Geben Sie an, eine andere bestehende Methode aufzurufen

Wir können eine Methode zur __call__ auch, ohne dass eine eigentliche __call__ Methode.

class MyClass:

    def __init__(self, val1, val2):
        self.val1 = val1
        self.val2 = val2

    def run(self, *args, **kwargs):
        print("hello", self.val1, self.val2, args, kwargs)

    __call__ = run

if __name__ == '__main__':
    (MyClass("Value1", "Value"))("world", 12, 213, 324, k1="one", k2="two")

Dies ermöglicht es, eine andere globale Funktion anstelle einer Methode zu deklarieren, aus welchem Grund auch immer (es kann einige Gründe geben, zum Beispiel können Sie diese Methode nicht ändern, aber Sie brauchen sie, um von der Klasse aufgerufen zu werden).

def run(self, *args, **kwargs):
    print("hello",self.val1, self.val2,  args, kwargs)

class MyClass:

    def __init__(self, val1, val2):
        self.val1 = val1
        self.val2 = val2

    __call__ = run

if __name__ == '__main__':
    (MyClass("Value1", "Value2"))("world", 12, 213, 324, k1="one", k2="two")

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X