Python中__init__和__call__有什么区别?

我想知道__init____call__方法之间的区别是什么。

例如:

 class test: def __init__(self): self.a = 10 def __call__(self): b = 20 

第一个用于初始化新创build的对象,并接收用于执行此操作的参数:

 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 
 >>> class A: ... def __init__(self): ... print "init" ... ... def __call__(self): ... print "call" ... >>> >>> A() init >>> A()() init call 

在Python中,函数是第一类对象,这意味着:函数引用可以在其他函数和/或方法的input中传递,并在其中执行。

(也称为对象)的实例可以看作是函数:将它们传递给其他方法/函数并调用它们。 为了达到这个目的, __call__类函数必须是专门的。

def __call__(self, [args ...])input一个可变数量的参数。 假设x是类X一个实例, x.__call__(1, 2) x(1,2)类似于调用x(1,2)实例本身作为函数

在Python中, __init__() __del__()被正确定义为Class Constructor(以及__del__()是Class Distructor)。 因此,在__init__()__call__()之间有一个净差别:第一个是构buildClass的一个实例,第二个使得这个实例可以被调用 ,而不会影响对象本身的生命周期(即__call__不会影响构build/销毁生命周期),但可以修改其内部状态(如下所示)。

例。

 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(7, 8) __call__ with (7,8) 

__call__使得类的实例可调用。 为什么要这么做?

技术上__init__在创build对象时由__new__调用一次,以便可以初始化。

但是在很多情况下,您可能需要重新定义对象,假设已经完成了对象,并且可能需要新的对象。 使用__call__您可以重新定义相同的对象,就像它是新的一样。

这只是一种情况,可以有更多。

__init__将被视为构造函数,其中__call__方法可以被任何次数的对象调用。 __init____call__函数都使用默认参数。

 >>> 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 ... >>> 

我们可以使用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") 

我会试着用一个例子来解释这个,假设你想从斐波那契数列中打印固定数量的术语。 请记住,斐波那契数列的前两项是1。 例如:1,2,3,5,8,13 ….

你希望包含fibonacci数字的列表只能初始化一次,之后应该更新。 现在我们可以使用__call__function。 阅读@mudit verma的答案。 这就像你想要的对象作为一个函数被调用,但不是在你称之为重新初始化。

例如:

 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__是第一次被实例化的时候被调用的,那么后面的对象被调用而不需要重新初始化。