我想了解__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
案例1:
class Example:
def __init__(self, a, b, c):
self.a=a
self.b=b
self.c=c
print("init", self.a, self.b, self.c)
运行:
Example(1,2,3)(7,8,9)
结果:
- init 1 2 3
- TypeError: 'Example' object is not callable
案例二:
class Example:
def __init__(self, a, b, c):
self.a=a
self.b=b
self.c=c
print("init", self.a, self.b, self.c)
def __call__(self, x, y, z):
self.x=x
self.y=y
self.z=z
print("call", self.x, self.y, self.z)
运行:
Example(1,2,3)(7,8,9)
结果:
- init 1 2 3
- call 7 8 9
上面已经提供了简短明了的答案。我想提供一些实际应用示例,与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;
}
}
}
__init__
是Python类中的一个特殊方法,它是一个类的构造方法。每当一个类的对象被构造时,它就会被调用或者我们可以说它初始化了一个新对象。
例如:
In [4]: class A:
...: def __init__(self, a):
...: print(a)
...:
...: a = A(10) # An argument is necessary
10
TypeError: __init__() missing 1 required positional argument: 'a'
,因为它需要一个参数a
,这是因为有__init__
。__call__
在类中被实现时,可以帮助我们将类实例作为函数调用。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__
函数。
__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.
接下来,我们以以下两种方式调用__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
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
obj = Person("John", "Smith")
obj.__call__("Hello, ") # Here
我希望为您提供一些快捷方式、语法糖以及一些可用的技术,但我还没有在当前答案中看到它们。
在许多情况下,例如需要进行API请求时,逻辑被封装在一个类中,我们真正需要的只是将数据提供给该类并立即运行它作为一个独立实体,此时可能不需要实例化类。这就是
instance = MyClass() # instanciation
instance() # run the instance.__call__()
# now instance is not needed
class HTTPApi:
def __init__(self, val1, val2):
self.val1 = val1
self.val2 = val2
def __call__(self, *args, **kwargs):
return self.run(args, kwargs)
def run(self, *args, **kwargs):
print("hello", self.val1, self.val2, args, kwargs)
if __name__ == '__main__':
# Create a class, and call it
(HTTPApi("Value1", "Value2"))("world", 12, 213, 324, k1="one", k2="two")
我们可以将一个方法声明为__call__
,而不必创建实际的__call__
方法。
class MyClass:
def __init__(self, val1, val2):
self.val1 = val1
self.val2 = val2
def run(self, *args, **kwargs):
print("hello", self.val1, self.val2, args, kwargs)
__call__ = run
if __name__ == '__main__':
(MyClass("Value1", "Value"))("world", 12, 213, 324, k1="one", k2="two")
def run(self, *args, **kwargs):
print("hello",self.val1, self.val2, args, kwargs)
class MyClass:
def __init__(self, val1, val2):
self.val1 = val1
self.val2 = val2
__call__ = run
if __name__ == '__main__':
(MyClass("Value1", "Value2"))("world", 12, 213, 324, k1="one", k2="two")
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")
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__
方法是什么 / 它是做什么的?”和“__call__
方法是什么 / 它是做什么的?”我没有先验地认为它们有任何关联,实际上它们没有关联 - 因此没有有意义的描述它们之间的“区别”。 - Karl Knechtel