Answers:
第一个用于初始化新创建的对象,并接收用于执行此操作的参数:
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__
什么?
在Python中,函数是一流的对象,这意味着:函数引用可以在输入中传递给其他函数和/或方法,并可以在它们内部执行。
可以将类的实例(也称为对象)当作函数来对待:将它们传递给其他方法/函数并调用它们。为了实现这一点,必须对__call__
类函数进行专门化处理。
def __call__(self, [args ...])
它以可变数量的参数作为输入。假定x
是Class的实例X
,x.__call__(1, 2)
类似于调用实例x(1,2)
或将实例本身作为函数。
在Python中,__init__()
正确定义为Class Constructor(以及__del__()
Class Destructor)。因此,__init__()
和之间有一个净的区别__call__()
:第一个建立一个Class的实例,第二个使该实例作为一个函数可调用而不会影响对象本身的生命周期(即__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
def __call__
简单地将替换为def update
,我们将为该类提供update
执行相同操作的方法。现在,它也可以修改内部状态(如果下面称为)s.update(7, 8)
。那么,就是__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 ...
>>>
__init__
将被视为构造函数,其中as __call__
方法可以多次用对象调用。这两个__init__
和__call__
功能做采取默认参数。
__init__
不是构造函数,而是__new__
。__init__
被称为__new__
__new__
创建类实例并接收一个类作为参数,而__init__
实例构造函数就是为什么要接收它self
。一种简单的查看方法是在调用a = Foo(1,2,3)
中将接收构造函数参数的函数为__init__
。
我将尝试通过一个示例来说明这一点,假设您要打印斐波那契数列中的固定数量的术语。请记住,斐波那契数列的前2个项是1。例如:1、1、2、3、5、8、13 ...
您希望包含斐波那契数字的列表仅被初始化一次,然后更新。现在我们可以使用该__call__
功能。阅读@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__
在第一次实例化该类时仅一次调用了输出,则稍后调用该对象而无需重新初始化。
您也可以使用__call__
方法来实现装饰器。
本示例摘自Python 3 Patterns,Recipes和Idioms
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__
在创建任何类的实例并初始化实例变量时也会调用。
例:
class User:
def __init__(self,first_n,last_n,age):
self.first_n = first_n
self.last_n = last_n
self.age = age
user1 = User("Jhone","Wrick","40")
而__call__
当你调用像任何其他函数的对象被调用。
例:
class USER:
def __call__(self,arg):
"todo here"
print(f"I am in __call__ with arg : {arg} ")
user1=USER()
user1("One") #calling the object user1 and that's gonna call __call__ dunder functions
__init__
是Python类中的一种特殊方法,它是类的构造方法。每当构造该类的对象时,就可以调用它,或者可以说它初始化了一个新对象。例:
In [4]: class A:
...: def __init__(self, a):
...: print(a)
...:
...: a = A(10) # An argument is necessary
10
如果我们使用A(),它将给出一个错误
TypeError: __init__() missing 1 required positional argument: 'a'
a
由于,它将需要1个参数__init__
。
........
__call__
在Class中实现时,可帮助我们将Class实例作为函数调用来调用。
例:
In [6]: class B:
...: def __call__(self,b):
...: print(b)
...:
...: b = B() # Note we didn't pass any arguments here
...: b(20) # Argument passed when the object is called
...:
20
在这里,如果我们使用B(),它就可以正常运行,因为这里没有__init__
函数。
__call__
允许返回任意值,而__init__
作为构造函数则隐式返回类的实例。正如其他答案正确指出的那样,__init__
它仅被调用一次,而__call__
如果已初始化的实例被分配给中间变量,则可以多次调用。
>>> 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中,我们再次创建另一个新实例instance1。在方案2中,我们只需修改已创建的instance1即可。__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")
__init__
当使用方法类调用初始化实例,而__call__
当调用该方法的实例被称为