python中, 一个类,如果实现了__call__方法,那么这个类的实例就是callable对象(可调用对象),__call__方法允许你像函数一样被调用, 这在程序设计上会带来非常大的便利性
python中, 一个类,如果实现了__call__方法,那么这个类的实例就是callable对象(可调用对象),下面用一个示例来解释这段话
class Stu:
    def __call__(self, *args, **kwargs):
        print('ok')
stu = Stu()
print(callable(stu))
stu()       # 像调用函数一样使用stu
程序输出结果
True
ok
如果类Stu没有实现__call__方法,执行stu(), 则会报错
TypeError: 'Stu' object is not callable
使用__call__方法,将类的实例对象伪装成函数,这种技术在python中被广泛使用
编写基于类的装饰器,就必须用到__call__方法
from functools import wraps
class SafeAdd:
    def __init__(self, func):
        self.func = func       # func是被装饰的函数
    def __call__(self, *args, **kwargs):
        if len(args) == 2:
            left = args[0]
            right = args[1]         # 获取参数并进行类型转换
            if not isinstance(left, (int, float)):
                left = float(left)
            if not isinstance(right, (int, float)):
                right = float(right)
            return left + right
        return None
@SafeAdd
def add(a, b):
    return a + b
print(add(3, 5))
print(add('3', '6'))
上面的代码还不足以阐述说明__call__方法在编写装饰器时所产生的作用,换一种写法,虽然我们正式使用装饰器时很少这样写,但更容易理解
def add(a, b):
    return a + b
safe_add = SafeAdd(add)     # add函数作为参数传入SafeAdd的初始化函数\__init__中
# safe_add是类SafeAdd的实例
print(safe_add(3, 5))
print(safe_add('3', '6'))
实例对象safe_add由于实现了__init__方法,因此可以像使用函数一样通过一对小括号来调用执行。
我们所使用flask, tornado, django 等web框架,无一例外的遵守WSGI协议,WSGI是一个协议,是一份约定,它规定服务器和应用程序之间如何传递数据,各自应该实现什么样的接口,以便彼此间配合工作。对于应用程序段,它只规定了3个简单的要求
第一条明确规定,应用程序必须是一个可调用对象,下面是一个简单的flask应用示例代码
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
    return 'Hello World!'
if __name__ == '__main__':
    app.run()
app就是应用程序,它是类Flask的实例,app是可调用对象,深入Flask类的源码可以发现,Flask类实现了__call__方法
def __call__(self, environ, start_response):
    """The WSGI server calls the Flask application object as the
    WSGI application. This calls :meth:`wsgi_app` which can be
    wrapped to applying middleware."""
    return self.wsgi_app(environ, start_response)
 
            扫描关注, 与我技术互动
QQ交流群: 211426309
 
                        分享日常研究的python技术和遇到的问题及解决方案