callable 对象
一个对象,只要实现了__call__方法,就可以通过小括号来调用,这一类对象,称之为可调用对象
In [1]: class Fn:
...: def __call__(self): # 在类中实现了__call__方法
...: print('abc')
...:
In [2]: f = Fn() # 实例化对象
In [8]: Fn()() # 类对象使用小括号来执行可调用对象
abc
In [3]: f # 直接执行实例化,获得的结果是这个对象的描述
Out[3]: <__main__.Fn at 0x7f5d95294f60>
In [4]: f() # 实例化加上小括号就是来调用__call__方法的
abc
确认对象是否是一个可调用对象可以使用callable方法来确认
In [5]: callable(f) # 确认实例化对象f是否是可调用对象
Out[5]: True
In [6]: callable(Fn()) # 确认类是否是可调用对象
Out[6]: True
In [7]: callable(lambda x: x) # 确认lambda匿名函数是否是可调用对象
Out[7]: True
callable方法的返回值都是bool类型的值
当类对象没有定义__call__方法的时候,是无法通过小括号来调用对象的
In [9]: class S:
...: pass
...:
In [11]: S()() # 因为类对象S没有__call__这个方法,因此无法使用小括号来调用对象
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-11-1018d1bf7eb9> in <module>()
----> 1 S()()
TypeError: 'S' object is not callable
可调用对象的传参
In [12]: class Adder:
...: def __call__(self,x ,y): # 定义了一个需要传递参数的__call__方法
...: return x + y
...:
In [13]: Adder()(3,5) # 当通过小括号来调用一个需要传递参数的可调用对象的时候,直接在第二组小括号里面传递指定的参数即可
Out[13]: 8
另外,在这里说明:第一组小括号是实例化对象的,第二组小括号才是调用对象的
__call__方法是为了拆分对象的逻辑
用__call__是来实现可调用对象,和闭包是殊途同归的,通常是为了封装一些内部的状态
就算不会用__call__也是没关系的,因为__call__是可以使用闭包来实现的,所以就算你不使用__call__也可以写出来高质量的代码