我想知道"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__
在 Python 中,函数是一级对象,这意味着。 函数引用可以被传递到其他函数和/或方法的输入中,并从它们内部执行。
类的实例 (又名对象),可以像对待函数一样对待。
将它们传递给其他方法/函数并调用它们。
为了达到这个目的,__call__
类函数必须被专门化。
def __call__(self, [args ...])
。
它接受一个可变数量的参数作为输入。
假设x
是类X
的一个实例,x.__call__(1, 2)
类似于调用x(1,2)
或实例本身作为函数。
在Python中,__init__()
被正确地定义为类构造函数(以及__del__()
是类破坏器)。
因此,__init__()
和__call__()
之间是有净区别的。
前者建立了一个Class的实例,后者使这个实例可以像函数一样被*调用,而不影响对象本身的生命周期(即
__call__
不影响构造/销毁的生命周期),但可以修改其内部状态(如下图所示)。
例子:{{12609965}。
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__
使一个类的实例可以调用。
为什么需要它?
从技术上讲,当创建对象时,__init__
会被__new__
调用一次,这样它就可以被初始化。
但是在很多情况下,你可能会想重新定义你的对象,比如你已经完成了你的对象,可能会发现需要一个新的对象。
通过__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 ...
>>>
我将试着用一个例子来解释这个问题,假设你想从斐波那契数列中打印出一个固定数量的项,请记住斐波那契数列的前两个项是1。 请记住,fibonacci数列的前2项是1。 例如:1, 1, 2, 3, 4, 5: 1, 1, 2, 3, 5, 8, 13....
你希望包含斐波那契数的列表只初始化一次,之后就应该更新。
现在我们可以使用__call__
功能。
阅读@mudit verma'的回答。
就像你希望对象可以作为一个函数调用,但不是每次调用时都要重新初始化。
例如:{{{12609968}}。
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__
。
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__
方法来代替实现[装饰器][1]。
这个例子取自 [Python 3 Patterns, Recipes and Idioms][2] 。
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")
输出。
[![在此输入图像描述][3]][3]
[1]: https://wiki.python.org/moin/PythonDecorators [2]: https://python-3-patterns-idioms-test.readthedocs.io/en/latest/#python-3-patterns-recipes-and-idioms [3]: https://i.stack.imgur.com/IzNSh.png
__init__
是Python类中的一个特殊方法,它是一个类的构造函数方法。
每当类的一个对象被构造时,它就会被调用,或者我们可以说它初始化了一个新的对象。
例子。
在[4]中。
A类。
...:
def __init__(self, a):
...:
print(a)
...:
...:
a = A(10) # 有必要有一个参数
10
如果我们使用A(),它将会给出一个错误信息
TypeError: __init__()缺少1个必要的位置参数。 'a'
,因为它需要1个参数a
,因为__init__
。
........
__call__
在类中实现后,可以帮助我们以函数调用的方式调用类实例。
例子:
在[6]:B类。
...:
def __call__(self,b):
...:
print(b)
...:
...:
b = B() # 注意我们没有传递任何参数。
...:
b(20) # 调用对象时传递的参数。
...:
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。
我们只需修改已经创建的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")