我想知道__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
当前回答
__init__将被视为构造函数,其中__call__方法可以被对象调用任意次数。__init__和__call__函数都接受默认参数。
其他回答
__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'
>>>
我们可以使用调用方法来使用其他类方法作为静态方法。
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__使类的实例可调用。 为什么需要它?
从技术上讲,__init__在对象创建时由__new__调用一次,以便可以初始化它。
但是在许多情况下,您可能想要重新定义对象,例如您已经完成了对象,并且可能发现需要一个新对象。使用__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")
输出:
__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__'