flask中Local源碼數據類型
首先明確:源碼中要構造的數據類型數是這樣的:
__storage__ = { 用線程或者協程的惟一標識爲鍵: {stack:[ctx(session/request) ,]} }
其次源碼用Local類構造數據類型,而後又用LocalStack類,做用是操做Local,讓咱們使用起來更方便,
LocalStack類中封裝了push方法,用來給調用Local添加數據,pop方法取數據,
下面來看看具體代碼怎麼實現的
Local類構造數據類型
#用線程或者協程的惟一標識爲鍵, try: # 協程惟一標識 from greenlet import getcurrent as get_ident except: # 進程惟一標識 from threading import get_ident class Local(object): # __slots__設置只容許調用的屬性 __slots__ = ('__storage__', '__ident_func__') def __init__(self): # __storage__ = {1231:{'stack':[]}} object.__setattr__(self, '__storage__', {}) #__storage__={} object.__setattr__(self, '__ident_func__', get_ident) #__ident_func__= get_ident #取數據 def __getattr__(self, name): try: return self.__storage__[self.__ident_func__()][name] except KeyError: raise AttributeError(name) #主要的數據構造過程 def __setattr__(self, name, value): # name=stack # value=[] #self對象調用屬性 ident = self.__ident_func__() #get_ident() storage = self.__storage__ #storage={} try: storage[ident][name] = value #storage={get_ident():{stack:[]}} except KeyError: storage[ident] = {name: value} #刪除數據 def __delattr__(self, name): try: del self.__storage__[self.__ident_func__()][name] except KeyError: raise AttributeError(name) #調用測試 obj = Local() obj.stack = [] obj.stack.append('胖虎') obj.stack.append('鹹魚') print(obj.stack) print(obj.stack.pop()) print(obj.stack) """ 數據構造結果: __storage__ = { 12312: {stack:[]} } """
LocalStack類操做Local
# LocalStack 操做Local的類,讓咱們用起來更方法 class LocalStack(object): def __init__(self): # 以Local對象做爲屬性 self._local = Local() # 向Local放值 def push(self,value): # 會先執行Local類裏面的__setattr__(self, name, value)方法,存儲數據 rv = getattr(self._local, 'stack', None) # self._local.stack =>local.getattr if rv is None: self._local.stack = rv = [] # self._local.stack =>local.setattr rv.append(value) # self._local.stack.append(666) return rv #調用local取數據 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: return stack[-1] else: return stack.pop() # def top(self): try: return self._local.stack[-1] except (AttributeError, IndexError): return None
最終實例化LocalStack類爲_request_ctx_stack
經過_request_ctx_stack對象來操做Local,而後把ctx.request / ctx.session放到Local數據類型中
#實例化 _request_ctx_stack = LocalStack() _request_ctx_stack.push(RequestContext()) def _lookup_req_object(arg): ctx = _request_ctx_stack.top() return getattr(ctx,arg) # ctx.request / ctx.session #把request和session都封裝到了Local中 request = functools.partial(_lookup_req_object,'request') session = functools.partial(_lookup_req_object,'session')