Vreau să știu diferența între __init__ " și " __call__
metode.
De exemplu:
class test:
def __init__(self):
self.a = 10
def __call__(self):
b = 20
Primul este folosit pentru a inițializa nou create obiect, și primește argumente folosite pentru a face asta:
class Foo:
def __init__(self, a, b, c):
# ...
x = Foo(1, 2, 3) # __init__
Cea de-a doua pune în aplicare funcția de operator call.
class Foo:
def __call__(self, a, b, c):
# ...
x = Foo()
x(1, 2, 3) # __call__
Definirea unui custom `call () metoda în meta-clasa a permite clasei's instanță pentru a fi numit în funcție, nu întotdeauna modificarea exemplu sine.
In [1]: class A:
...: def __init__(self):
...: print "init"
...:
...: def __call__(self):
...: print "call"
...:
...:
In [2]: a = A()
init
In [3]: a()
call
În Python, funcțiile sunt prima clasă de obiecte, acest lucru înseamnă: funcția de referințe poate fi trecut în intrări pentru alte funcții și/sau de metode și executat din interiorul ei.
Cazuri de Clase (aka Obiecte), pot fi tratate ca funcții: le trece la alte metode/funcții și le numim. În scopul de a realiza acest lucru, `call clasa funcție trebuie să fie de specialitate.
def __call__(self, [args ...])
Este nevoie ca date de intrare un număr variabil de argumente. Presupunând că " x " fiind un exemplu de Clasa X
, x.__de apel__(1, 2)
este analog asteptare x(1,2)
sau de exemplu, în sine, ca o funcție.
În Python, __init__ () este definită în mod corespunzător în Clasa Constructor (precum
del()este Clasa Destructor). Prin urmare, nu există o distincție netă între
init () " și " call(): primul construiește o instanță a Clasei de sus, al doilea face astfel de exemplu *nevărsat* ca o funcție ar fi, fără a afecta ciclul de viață al obiectului în sine (de exemplu,
call` nu are impact construcție/distrugere a ciclului de viață), dar se poate modifica starea sa internă (așa cum se arată mai jos).
Exemplu.
class Stuff(object):
def __init__(self, x, y, range):
super(Stuff, self).__init__()
self.x = x
self.y = y
self.range = range
def __call__(self, x, y):
self.x = x
self.y = y
print '__call__ with (%d,%d)' % (self.x, self.y)
def __del__(self):
del self.x
del self.y
del self.range
>>> s = Stuff(1, 2, 3)
>>> s.x
1
>>> s(7, 8)
__call__ with (7,8)
>>> s.x
7
__call__
face instanță a unei clase nevărsat.
De ce ar fi necesar?
Din punct de vedere tehnic __init__
este numit o dată prin __noi,__
când obiectul este creat, astfel încât acesta poate fi inițializat.
Dar există mai multe scenarii în cazul în care ați putea dori pentru a redefini obiect, să spunem că ai terminat cu obiectul, și-ar putea găsi o nevoie pentru un obiect nou. Cu __call__
puteți redefini același obiect ca și cum ar fi nou.
Acesta este doar un caz, nu poate fi mult mai multe.
>>> class A:
... def __init__(self):
... print "From init ... "
...
>>> a = A()
From init ...
>>> a()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: A instance has no __call__ method
>>>
>>> class B:
... def __init__(self):
... print "From init ... "
... def __call__(self):
... print "From call ... "
...
>>> b = B()
From init ...
>>> b()
From call ...
>>>
Voi încerca să explic acest lucru, folosind un exemplu, să presupunem că ai vrut să imprimați un număr fix de termeni din seria fibonacci. Amintiți-vă că primele 2 termeni din seria fibonacci sunt 1s. De exemplu: 1, 1, 2, 3, 5, 8, 13....
Vrei o listă cu numerele lui fibonacci pentru a fi inițializate doar o singură dată și după aceea ar trebui să actualizare. Acum putem folosi `call functionalitate. Citiți @mudit verma's a răspunde. L's ca vrei obiect de a fi executate ca o funcție, dar nu re-initializat vreodată ytime-ai spune.
De exemplu:
class Recorder:
def __init__(self):
self._weights = []
for i in range(0, 2):
self._weights.append(1)
print self._weights[-1]
print self._weights[-2]
print "no. above is from __init__"
def __call__(self, t):
self._weights = [self._weights[-1], self._weights[-1] + self._weights[-2]]
print self._weights[-1]
print "no. above is from __call__"
weight_recorder = Recorder()
for i in range(0, 10):
weight_recorder(i)
De ieșire este:
1
1
no. above is from __init__
2
no. above is from __call__
3
no. above is from __call__
5
no. above is from __call__
8
no. above is from __call__
13
no. above is from __call__
21
no. above is from __call__
34
no. above is from __call__
55
no. above is from __call__
89
no. above is from __call__
144
no. above is from __call__
Dacă observați ieșire `init a fost numit doar o singură dată ca's, atunci când clasa a fost creata pentru prima dată, mai târziu, pe obiect a fost numit, fără a re-inițializarea.
Puteți folosi, de asemenea, __call__
metodă în favoarea punere în aplicare decorațiuni.
Acest exemplu preluat din Python 3 Modele, Rețete și Expresii
class decorator_without_arguments(object):
def __init__(self, f):
"""
If there are no decorator arguments, the function
to be decorated is passed to the constructor.
"""
print("Inside __init__()")
self.f = f
def __call__(self, *args):
"""
The __call__ method is not called until the
decorated function is called.
"""
print("Inside __call__()")
self.f(*args)
print("After self.f( * args)")
@decorator_without_arguments
def sayHello(a1, a2, a3, a4):
print('sayHello arguments:', a1, a2, a3, a4)
print("After decoration")
print("Preparing to call sayHello()")
sayHello("say", "hello", "argument", "list")
print("After first sayHello() call")
sayHello("a", "different", "set of", "arguments")
print("After second sayHello() call")
Ieșire:
__init__
este o metodă specială în Python clase, este metoda constructor pentru o clasa. Este numit ori de câte ori un obiect al clasei este construit sau putem spune că inițializează un obiect nou.
Exemplu:
În [4]: clasa a: ...: def __init__(self, o): ...: print(a) ...: ...: o = O(10) # Un argument este necesar 10
Dacă vom folosi Un(), aceasta vă va da o eroare
TypeError: __init__() lipsă 1 necesar de poziție argument: 'un'
deoarece necesită 1 argument " a " pentru a __init__
.
........
__call__
atunci când sunt implementate în Clasa ne ajută invoca în instanță de Clasă ca un apel de funcție.
Exemplu:
În [6]: clasa B: ...: def __call__(self,b): ...: print(b) ...: ...: b = B() # Notă ne-am't trece orice argumente aici ...: b(20) # Argument trecut atunci când obiectul este numit ...: 20
Aici, dacă vom folosi B(), ruleaza foarte bine, deoarece ea nu't au o `init funcția aici.
__call__
permite să se întoarcă valori arbitrare, în timp ce __init__
fiind un constructor returnează exemplu de clasă în mod implicit. Ca și alte răspunsuri în mod corespunzător a subliniat, __init__
este numit doar o singură dată, în timp ce-l's posibil pentru a apela __call__
de mai multe ori, în cazul în care inițializat exemplu este atribuit variabile intermediare.
>>> class Test:
... def __init__(self):
... return 'Hello'
...
>>> Test()
Traceback (most recent call last):
File "<console>", line 1, in <module>
TypeError: __init__() should return None, not 'str'
>>> class Test2:
... def __call__(self):
... return 'Hello'
...
>>> Test2()()
'Hello'
>>>
>>> Test2()()
'Hello'
>>>
Scurt și dulce răspunsurile sunt deja prevăzute mai sus. Vreau sa oferi unele punerea în practică, în comparație cu Java.
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
Notă: scenariul 1 și scenariul 2 pare aceeași în ceea ce privește rezultatul de ieșire.
Dar în scenario1, avem din nou de a crea alta nouă instanță instance1. În scenario2,
noi pur și simplu modifica deja create instance1. __call__
este benefic aici ca sistemul nu't nevoie pentru a crea noi exemplu.
Echivalentul în 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;
}
}
}
Putem folosi call metoda de a folosi alte metode de clasă ca metode statice.
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")