Werkzeug的Local系列(3) - 模仿Werkzeug的Local和LocalProxy

模仿Werkzeug的Local和LocalProxy

根据之前的需求,尝试编写代码:


class Request(object):

    def __init__(self):
        self.url = 'baidu.com'

class User(object):

    def __init__(self):
        self.owner = 'www'

class Local:
    def __init__(self):
        self._objs = {}
        self._objs['request'] = Request()
        self._objs['user'] = User()

    def __getattr__(self, name):
        print('Local.__getattr__')
        return self._objs[name]

    def __call__(self, name):
        return LocalProxy(self, name)

class LocalProxy(object):

    def __init__(self, local, name):
        self._local = local
        self._name = name

    def _get_current_obj(self):
        print('_get_current_obj')
        return getattr(self._local, self._name)

    def __getattr__(self, name):
        print('SpamProxy.__getattr__')
        return getattr(self._get_current_obj(), name)
    
    def __setattr__(self, name ,value):
        if name.startswith('_'):
            super().__setattr__(name, value)
        else:
            setattr(self._obj, name, value)
    
    def __delattr__(self, name):
        print('SpamProxy.__delattr__')
        if name.startswith('_'):
            super().__delattr__(name)
        else:
            print('SpamProxy', name)
            delattr(self._obj, name)

l = Local()

request = l('request')
print(request)
print(request.url)

user = l('user') 
print(user.owner)

输出结果:

<main.LocalProxy object at 0x7f74e1b0d2b0>
SpamProxy.getattr
_get_current_obj
Local.getattr
baidu.com
SpamProxy.getattr
_get_current_obj
Local.getattr
www

2 结论

通过该实例,我们实现了:

  • Local管理Request和User对象
  • LocalProxy实现代理访问Local管理的多个对象

当然Werkzeug的Local实现比示例复杂:

  • Local的_objs增加线程(协程)维度
  • Request和User等管理的对象是动态添加,示例中是固定的

后面的文章将接讲解Werkzeug的Local、LocalProxy、LocalManager和LocalProxy。

你可能感兴趣的:(Werkzeug的Local系列(3) - 模仿Werkzeug的Local和LocalProxy)