>>> from env_helper import info; info()
页面更新时间: 2020-03-08 09:59:17
操作系统/OS: Linux-4.19.0-8-amd64-x86_64-with-debian-10.3 ;Python: 3.7.3

13.3. 神奇的__call__与返回函数

__call__ 是一个很神奇的特性,只要某个类型中有 __call__ 方法,,我们可以把这个类型的对象当作函数来使用。

13.3.1. 函数对象

也许说的比较抽象,举个例子就会明白。

>>> f = abs
>>> '__call__' in dir(f)
True

上例中的f对象指向了abs类型,由于f对象中有__call__方法,因此f(-10)实现了对abs(-10)的重载。

>>> f(-10)
10

由于变量/对象/实例可以指向函数,而函数能够接受变量,因此可以看出函数可以接受另一个函数作为参数,所以__call__就实现装饰器的基础。

13.3.2. 扩展部分:返回函数

函数或类一般有返回值,而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__的内建方法。