__call__
是一个很神奇的特性,只要某个类型中有 __call__
方法,就可以把这个类型的对象当作函数来使用。
f = abs
'__call__' in dir(f)
True
上例中的 f
对象指向了 abs
类型,由于 f
对象中有__call__
方法,
因此 f(-10)
实现了对 abs(-10)
的重载。
f(-10)
10
由于变量/对象/实例可以指向函数,而函数能够接受变量,
因此可以看出函数可以接受另一个函数作为参数,所以__call__
就实现装饰器的基础。
函数或类一般有返回值,而python中有一个神奇的特性就是返回函数。
def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum
f = lazy_sum(1,3,5,7,9)
f
<function __main__.lazy_sum.<locals>.sum()>
'__call__' in dir(f)
True
f()
25
为什么返回函数能够这么神奇,咱们一探究竟。
dir(f)
['__annotations__',
'__call__',
'__class__',
...
'__getattribute__',
...
'__setattr__',
]
查看一下 type
,真相打败,原来是因为f里有__call__
的内建方法。