我想了解__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__
方法被使用,而当调用实例时,__call__
方法被调用。 - pratikm __call__
的实际用途是什么? - mrgloom定义一个自定义的__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__
不仅允许将一个实例用作函数,还定义了当实例被用作函数时要执行的函数体。 - Arthur在Python中,函数是一等对象,这意味着:函数引用可以作为输入传递给其他函数和/或方法,并且可以从其中执行。
类的实例(也称为对象)可以像函数一样处理:将它们传递给其他方法/函数并调用它们。为了实现这一点,必须专门化__call__
类函数。
def __call__(self, [args...])
它以可变数量的参数作为输入。假设x
是类X
的实例,则x.__call__(1,2)
类似于调用x(1,2)
或将实例本身作为函数。
在Python中,__init__()
被正确定义为类构造函数(以及__del__()
是类析构函数)。因此,__init__()
和__call__()
之间存在明显区别:前者构建类实例,后者使该实例可调用,就像函数一样,而不影响对象本身的生命周期(即__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
def __call__
直接替换为 def update
,我们就给类添加了一个执行相同操作的 update
方法。如果像下面这样调用 s.update(7, 8)
,它现在也可以修改内部状态。因此,__call__
只是语法糖吗? - Alex Povel__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 ...
>>>
__init__
被视为构造函数,而 __call__
方法可以被对象调用任意次数。 __init__
和 __call__
函数都可以使用默认参数。
__init__
不是构造函数,但 __new__
是。__init__
在 __new__
之后立即被调用。 - dallonsi__new__
创建类实例并接收一个类作为参数,而__init__
是实例构造函数,因此它接收self
。一个简单的方法来理解这一点是在调用a = Foo(1,2,3)
时,将接收构造函数参数的函数将是__init__
。 - luv2learn__call__
功能。阅读@mudit verma的答案。这就像您希望对象可调用为函数,但不会在每次调用时重新初始化它。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__
只在类被实例化为第一次时调用,之后对象被调用时不需要重新初始化。
__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'
>>>
因此,__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
你也可以使用__call__
方法来代替实现装饰器。
这个例子摘自Python 3 Patterns, Recipes and Idioms
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__
方法是什么 / 它是做什么的?”和“__call__
方法是什么 / 它是做什么的?”我没有先验地认为它们有任何关联,实际上它们没有关联 - 因此没有有意义的描述它们之间的“区别”。 - Karl Knechtel