Werkzeug之LocalStack源码解析
原博文地址
http://liuyajing.coding.me/blogs/python/2018/werkzeug-localstack/
一、引入
最近在阅读 Flask 的源码,遇到三个概念:Local 、 LocalStack 和 LocalProxy ,本文主要就针对 LocalStack 概念及其源码进行原理剖析。
二、原理
这个类类似于:class:Local,但是在 storage[ident] 中存放的是一个 key 为 stack,value 为 一个堆列表的形式,例如:
>>> ls = LocalStack()
>>> ls.push(42)
>>> ls.top
42
>>> ls.push(23)
>>> ls.top
23
>>> ls.pop()
23
>>> ls.top
42
'''
它们可以通过使用:class:LocalManager或使用:func:release_local函数强制释放,但正确的方法是在使用后从堆栈中弹出元素。 当堆栈为空时,它将不再绑定到当前上下文(并因此释放)。
通过不带参数调用实例方法,它返回一个代理,该代理解析为堆栈中最顶层的元素。
'''
三、LocalStack
1. init
def __init__(self):
self._local = Local()
'''
__init__方法生成了一个新的Local实例, 并赋值给了_local属性。
'''
2. release_local
def __release_local__(self):
self._local.__release_local__()
'''
此方法调用Local实例的__release_local__方法。
'''
3. get__ident_func_
def _get__ident_func__(self):
return self._local.__ident_func__
'''
此方法返回Local实例中获取ident的方法函数。
'''
4. set__ident_func_
def _set__ident_func__(self, value):
object.__setattr__(self._local, '__ident_func__', value)
__ident_func__ = property(_get__ident_func__, _set__ident_func__)
del _get__ident_func__, _set__ident_func__
'''
此方法设置Local实例中获取ident的方法函数。
'''
5. call
def __call__(self):
def _lookup():
rv = self.top
if rv is None:
raise RuntimeError('object unbound')
return rv
return LocalProxy(_lookup)
'''
在类中实现了__call__方法,那么实例对象也将成为一个可调用对象,那就可以像函数一样调用它。
'''
6. push
def push(self, obj):
"""Pushes a new item to the stack"""
rv = getattr(self._local, 'stack', None)
if rv is None:
self._local.stack = rv = []
rv.append(obj)
return rv
'''
结合Local源码的分析,我们知道push方法实现的是将对象obj放入字典Local.__storage__[ident]中key为 stack 对应的堆栈结构 (列表) 的value中。
'''
7. pop
def pop(self):
"""Removes the topmost item from the stack, will return the
old value or `None` if the stack was already empty.
"""
stack = getattr(self._local, 'stack', None)
if stack is None:
return None
elif len(stack) == 1:
release_local(self._local)
return stack[-1]
else:
return stack.pop()
'''
结合Local源码的分析,我们知道pop方法实现的是将从字典Local.__storage__[ident]中key为 stack 对应的堆栈结构 (列表) 取出最后一个元素。
'''
8. top
@property
def top(self):
"""The topmost item on the stack. If the stack is empty,
`None` is returned.
"""
try:
return self._local.stack[-1]
except (AttributeError, IndexError):
return None
'''
结合Local源码的分析,我们知道top方法实现的是返回字典Local.__storage__[ident]中key为 stack 对应的堆栈结构 (列表) 的最后一个元素。
'''
四、总结
'''
LocalStack 是在 Local 的基础上进行了二次封装,只是 LocalStack 维护的数据中 key 是固定的, 就是 stack, 而 value 值是栈的形式。
'''