Python中的魔法方法深入理解

2019-10-06 12:15:32丽君

            # 从LocalProxy(partial(_lookup_req_object, 'request'))看来
            # 通过调用self.__local()方法,我们得到了 partial(_lookup_req_object, 'request')()
            # 也就是 ``_request_ctx_stack.top.request``
            return self.__local()
        try:
            return getattr(self.__local, self.__name__)
        except AttributeError:
            raise RuntimeError('no object bound to %s' % self.__name__)

    # 接下来就是一大段一段的Python的魔法方法了,Local Proxy重载了(几乎)?所有Python
    # 内建魔法方法,让所有的关于他自己的operations都指向到了_get_current_object()
    # 所返回的对象,也就是真正的被代理对象。

    ... ...
    __setattr__ = lambda x, n, v: setattr(x._get_current_object(), n, v)
    __delattr__ = lambda x, n: delattr(x._get_current_object(), n)
    __str__ = lambda x: str(x._get_current_object())
    __lt__ = lambda x, o: x._get_current_object() < o
    __le__ = lambda x, o: x._get_current_object() <= o
    __eq__ = lambda x, o: x._get_current_object() == o
    __ne__ = lambda x, o: x._get_current_object() != o
    __gt__ = lambda x, o: x._get_current_object() > o
    __ge__ = lambda x, o: x._get_current_object() >= o
    ... ...

事情到了这里,我们在文章开头的第二个疑问就能够得到解答了,我们之所以不需要使用get_request() 这样的方法调用来获取当前的request对象,都是LocalProxy的功劳。

LocalProxy作为一个代理,通过自定义魔法方法。代理了我们对于request的所有操作, 使之指向到真正的request对象。

怎么样,现在知道了 request.args 不是它看上去那么简简单单的吧。

现在,让我们来看看第二个问题,在多线程的环境下,request是怎么正常工作的呢? 还是让我们回到globals.py吧:

from functools import partial
from werkzeug.local import LocalStack, LocalProxy


def _lookup_req_object(name):
    top = _request_ctx_stack.top
    if top is None:
        raise RuntimeError('working outside of request context')
    return getattr(top, name)

# context locals