Я хочу знать разницу между методами __init__
и __call__
.
Например:
class test:
def __init__(self):
self.a = 10
def __call__(self):
b = 20
Первый используется для инициализации вновь созданного объекта и получает аргументы, используемые для этого:
class Foo:
def __init__(self, a, b, c):
# ...
x = Foo(1, 2, 3) # __init__
Второй реализует оператор вызова функции.
class Foo:
def __call__(self, a, b, c):
# ...
x = Foo()
x(1, 2, 3) # __call__
Определение пользовательского метода __call__()
в метаклассе позволяет вызывать экземпляр класса как функцию, не всегда изменяя сам экземпляр.
In [1]: class A:
...: def __init__(self):
...: print "init"
...:
...: def __call__(self):
...: print "call"
...:
...:
In [2]: a = A()
init
In [3]: a()
call
В Python функции являются объектами первого класса, это означает, что: ссылки на функцию может быть передан в материалы для других функций и/или методов, и выполнены внутри них.
Экземпляры классов (объекты ака), может рассматриваться как если бы они были функциями: пройдите их, чтобы другие методы/функции и называть их. Для того чтобы добиться этого, функция класса__звоните__
должен быть специализированным.
деф и __Call__(самовыдвижение, [аргументы ...])
Он принимает в качестве входного сигнала переменное число аргументов. Предполагая, что " Х " быть экземпляром класса Х
, Х.__вызов__(1, 2)
аналогично вызову х(1,2)
или сам экземпляр как функция.
В Python, __инит__ ()
- это правильно определить как конструктор класса (а также __дель__ ()
- это деструктор класса). Таким образом, существует четкое разделение между __инит__ () " и " и__Call__()
: первый создает экземпляр класса, второй делает такой экземпляр отзывной как функция бы без ущерба для жизненного цикла самого объекта (т. е. __звоните__
не влияет на построение и уничтожение жизненного цикла), но он может изменить свое внутреннее состояние (как показано ниже).
Пример.
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
__звоните__
делает экземпляр класса, вызвать.
Зачем это требуется?
Технически __init__, которая вызывается один раз
Новый - когда объект создан, так что он может быть инициализирован.
Но существует множество сценариев, где вы, возможно, захотите пересмотреть ваш объект, скажем, вы закончите с Вашего объекта, и может найти необходимость для нового объекта. С __звоните__
вы можете переопределить один и тот же объект, как если бы это были новые.
Это только один случай, там может быть много больше.
>>> 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 ...
>>>
Я постараюсь объяснить это на примере, Предположим, вы хотите напечатать определенное количество терминов из ряда Фибоначчи. Помните, что первые 2 серии Фибоначчи 1С. Например: 1, 1, 2, 3, 5, 8, 13....
Вы хотите, чтобы список, содержащий числа Фибоначчи должен быть инициализирован только один раз и после этого он должен обновляться. Теперь мы можем использовать функции __звоните__
. Читать @мудить Верма'ы ответ. Это's, как вы хотите, чтобы объект, который будет вызываться как функция, но не повторно инициализировать никогда ytime вы это называете.
Например:
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)
Вывод:
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__
Если соблюдать выход `init, которая была вызвана только один раз, что's, когда класс был инстанцирован в первый раз, позже стали называться без повторной инициализации.
Вы также можете использовать метод `звоните в пользу реализации декораторов.
Этот пример взят из на Python 3 Шаблоны, рецепты и идиомы
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")
Вывод:
`init, которая является специальным методом в классы в Python, это метод, конструктор класса. Она вызывается при каждом создании объекта класса или мы можем сказать, что инициализирует новый объект. Пример:
В [4]: класс: ...: деф __инит__(самостоятельная, а): ...: печать(а) ...: ...: а = а(10) # Аргумент необходимо 10
Если мы используем(), то выдаст ошибку
Ошибку TypeError: __инит__() отсутствует 1 требуется позиционный аргумент: 'Это'
так как он требует 1 аргумент а
из-за __init и__
.
........
__звоните__
при реализации в классе помогает нам ссылаться на экземпляр класса, как вызов функции.
Пример:
В [6]: класс B: ...: деф __вызов__(самовыдвижение,б): ...: печать(б) ...: ...: б = б() # обратите внимание, мы не'т пройти любые аргументы здесь ...: б(20) аргумент # прошло, когда объект называется ...: 20
Вот если мы будем использовать B(), он работает просто отлично, потому что он не'т у `init в функции - вот.
__звоните__
позволяет возвращать произвольные значения, в то время как __init__, которая представляет собой конструктор возвращает экземпляр класса неявно. Как и другие ответы правильно указал,
init, которая вызывается только один раз, в то время как он'ы можно назвать множественнойзвоните раз, в случае инициализации экземпляра присваивается промежуточной переменной.
>>> 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'
>>>
Коротким и сладким ответы уже приведены выше. Я хочу представить некоторые практические реализации по сравнению с 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
Примечание: сценарий 1 и сценарий 2 выглядит так же, с точки зрения результата. Но в сценарий1, мы снова создаем еще один новый экземпляр экземпляр1. В scenario2, мы просто модифицировать уже созданные экземпляр1. `иCall - это выгодно, здесь как система не'т нужно создать новый экземпляр.
Эквивалент в 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;
}
}
}
Мы можем использовать и Call метод, чтобы использовать другие методы класса как статические методы.
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")