__call__是一個很神奇的特性,只要某個類型中有__call__方法,,我們可以把這個類型的對象當作函數來使用。
也許說的比較抽象,舉個例子就會明白。
In [107]: f = abs In [108]: f(-10) Out[108]: 10 In [109]: dir(f) Out[109]: ['__call__', '__class__', '__delattr__', '__dir__', ...]
上例中的f對象指向了abs類型,由於f對象中有__call__方法,因此f(-10)實現了對abs(-10)的重載。
ps:由於變量/對象/實例可以指向函數,而函數能夠接受變量,因此可以看出函數可以接受另一個函數作為參數,所以__call__就實現裝飾器的基礎。
擴展部分:返回函數
函數或類一般有返回值,而python中有一個神奇的特性就是返回函數。
In [134]: %cpaste Pasting code; enter '--' alone on the line to stop or use Ctrl-D. : :def lazy_sum(*args): : def sum(): : ax = 0 : for n in args: : ax = ax + n : return ax : return sum :-- In [135]: f = lazy_sum(1,3,5,7,9) In [136]: f Out[136]: <function __main__.lazy_sum.<locals>.sum> In [137]: f() Out[137]: 25
為什么返回函數能夠這么神奇,咱們一探究竟。
In [138]: dir(f) Out[138]: ['__annotations__', '__call__', '__class__', ... '__getattribute__', ... '__setattr__', ]
查看一下type,真相打敗,原來是因為f里有__call__的內建方法。