我想知道__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 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__
其他回答
因此,当你创建任何类的实例并初始化实例变量时,__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
我将尝试用一个例子来解释这一点,假设您想从斐波那契数列中输出固定数量的项。记住斐波那契数列的前两项都是1。例:1,1,2,3,5,8,13 ....
您希望包含斐波那契数的列表只初始化一次,然后更新。现在我们可以使用__call__函数了。阅读@mudit verma的回答。这就像你希望对象作为函数可调用,但不是每次调用时都重新初始化。
Eg:
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__只被调用了一次,那就是类第一次实例化的时候,后来对象被调用而没有重新初始化。
__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__'
定义自定义__call__()方法允许将类的实例作为函数调用,而不总是修改实例本身。
In [1]: class A:
...: def __init__(self):
...: print "init"
...:
...: def __call__(self):
...: print "call"
...:
...:
In [2]: a = A()
init
In [3]: a()
call
在Python中,函数是一级对象,这意味着:函数引用可以在输入中传递给其他函数和/或方法,并在它们内部执行。
类的实例(又名对象),可以像函数一样对待:将它们传递给其他方法/函数并调用它们。为了实现这一点,__call__类函数必须特殊化。
Def __call__(self, [args…]) 它接受可变数量的参数作为输入。假设x是类x的实例,x.__call__(1,2)类似于将x(1,2)或实例本身作为函数调用。
在Python中,__init__()被正确地定义为类构造函数(以及__del__()是类析构函数)。因此,在__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