我想知道__init__和__call__方法之间的区别。
例如:
class test:
def __init__(self):
self.a = 10
def __call__(self):
b = 20
我想知道__init__和__call__方法之间的区别。
例如:
class test:
def __init__(self):
self.a = 10
def __call__(self):
b = 20
当前回答
>>> 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__()方法允许将类的实例作为函数调用,而不总是修改实例本身。
In [1]: class A:
...: def __init__(self):
...: print "init"
...:
...: def __call__(self):
...: print "call"
...:
...:
In [2]: a = A()
init
In [3]: a()
call
你也可以使用__call__方法来实现装饰器。
这个例子来自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")
输出:
方法用于使对象像函数一样工作。
>>> 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
<*There is no __call__ method so it doesn't act like function and throws error.*>
>>>
>>> class B:
... def __init__(self):
... print "From init ... "
... def __call__(self):
... print "From call it is a function ... "
...
>>> b = B()
From init ...
>>> b()
From call it is a function...
>>>
<* __call__ method made object "b" to act like function *>
我们也可以把它传递给一个类变量。
class B:
a = A()
def __init__(self):
print "From init ... "
__init__()可以:
初始化类的实例。 被叫了很多次。 只返回None。
__call__()可以像实例方法一样自由使用。
例如,Person类有__init__()和__call__(),如下所示:
class Person:
def __init__(self, f_name, l_name):
self.f_name = f_name
self.l_name = l_name
print('"__init__()" is called.')
def __call__(self, arg):
return arg + self.f_name + " " + self.l_name
现在,我们创建并初始化Person类的实例,如下所示:
# Here
obj = Person("John", "Smith")
然后调用__init__(),如下所示:
"__init__()" is called.
接下来,我们以如下所示的2种方式调用__call__():
obj = Person("John", "Smith")
print(obj("Hello, ")) # Here
print(obj.__call__("Hello, ")) # Here
然后调用__call__(),如下所示:
"__init__()" is called.
Hello, John Smith # Here
Hello, John Smith # Here
并且,__init__()可以多次调用,如下所示:
obj = Person("John", "Smith")
print(obj.__init__("Tom", "Brown")) # Here
print(obj("Hello, "))
print(obj.__call__("Hello, "))
然后,调用__init__(), Person类的实例被重新初始化,并从__init__()返回None,如下所示:
"__init__()" is called.
"__init__()" is called. # Here
None # Here
Hello, Tom Brown
Hello, Tom Brown
并且,如果__init__()不返回None,我们调用__init__(),如下所示:
class Person:
def __init__(self, f_name, l_name):
self.f_name = f_name
self.l_name = l_name
print('"__init__()" is called.')
return "Hello" # Here
# ...
obj = Person("John", "Smith") # Here
出现以下错误:
__init__()应该返回None,而不是'str'
并且,如果Person类中没有定义__call__:
class Person:
def __init__(self, f_name, l_name):
self.f_name = f_name
self.l_name = l_name
print('"__init__()" is called.')
# def __call__(self, arg):
# return arg + self.f_name + " " + self.l_name
然后,我们调用obj("Hello, "),如下所示:
obj = Person("John", "Smith")
obj("Hello, ") # Here
出现以下错误:
'Person'对象不可调用
同样,我们调用obj。__call__("Hello, ")如下所示:
obj = Person("John", "Smith")
obj.__call__("Hello, ") # Here
出现以下错误:
AttributeError: 'Person'对象没有属性'__call__'
上面已经给出了简短而甜蜜的答案。我想提供一些与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。在scenario2, 我们只需修改已经创建的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;
}
}
}