Python的魔法方法__call__()和__init__()拾遗

__call__()

我们常听到:Python中一切都是对象。

这句话对Python中的函数也是同样适用的。事实上,函数在Python中是一级对象,即Python中的函数可以作为输入参数传递到其他的函数/方法中,并在其中被执行。

同时,对象(实例化的类)可以被当做函数对待。也就是说,可以给对象传递参数,达到函数的效果。比如这样:

1
this_is_call(arg1, arg2)

要把一个实例对象做为函数调用,需要在类中实现_call_()方法。也就是我们要在类中实现如下方法:

1
2
def __call__(self, *args):
pass

假设x是X类的一个实例。那么调用x.__call__(1,2)等同于调用x(1,2)。这个实例本身在这里相当于一个函数。

看到这里你可能会有一点疑惑,这哥们儿有点眼熟儿啊,和__init__()有啥区别?

没错,但后者是初始化实例时用的,具体区别如下:

  1. __init__()的作用是初始化某个类的一个实例。
  2. __call__()的作用是使实例能够像函数一样被调用,同时不影响实例本身的生命周期(__call__()不影响一个实例的构造和析构)。但是__call__()可以用来改变实例的内部成员的值。

代码对比:

1
2
3
4
5
6
7
8
9
10
11
12
13
class X(object):
def __init__(self, a, b, range):
self.a = a
self.b = b
self.range = range
def __call__(self, a, b):
self.a = a
self.b = b
print('__call__ with ({}, {})'.format(self.a, self.b))
def __del__(self, a, b, range):
del self.a
del self.b
del self.range

调用结果:

1
2
3
>>> xInstance = X(1, 2, 3)	# 创建对象,用的__init__()
>>> xInstance(1,2) # 调用对象(这个对象已经是一个函数了),这时用的__call__()
__call__ with (1, 2)