赞
踩
>>from threading import local
>#实例化local函数
>>thread_local_data = local()
>#定义user_name='Jim'
>>thread_local_data.user_name="Jim"
>#通过key"user_name"获取value"Jim"
>>thread_local_data.user_name
'Jim'
from werkzeug.local import Local, LocalManager
# 实例化Local函数
local = Local()
# 实例化LocalManager函数
local_manager = LocalManager([local])
def application(environ, start_response):
local.request = request = Request(environ)
...
# make_middleware会确保当request结束时,\
# 所有存储于local中的对象的reference被清除
application = local_manager.make_middleware(application)
# 在有greenlet的情况下,get_indent实际获取的是greenlet的id,而没有greenlet的情况下获取的是thread id try: from greenlet import getcurrent as get_ident except ImportError: try: from thread import get_ident except ImportError: from _thread import get_ident class Local(object): __slots__ = ('__storage__', '__ident_func__') def __init__(self): object.__setattr__(self, '__storage__', {}) object.__setattr__(self, '__ident_func__', get_ident) def __iter__(self): return iter(self.__storage__.items()) # 当调用Local对象时,返回对应的LocalProxy def __call__(self, proxy): """Create a proxy for a name.""" return LocalProxy(self, proxy) # Local类中特有的method,用于清空greenlet id或线程id对应的dict数据 def __release_local__(self): self.__storage__.pop(self.__ident_func__(), None) def __getattr__(self, name): try: return self.__storage__[self.__ident_func__()][name] except KeyError: raise AttributeError(name) def __setattr__(self, name, value): ident = self.__ident_func__() storage = self.__storage__ try: storage[ident][name] = value except KeyError: storage[ident] = {name: value} def __delattr__(self, name): try: del self.__storage__[self.__ident_func__()][name] except KeyError: raise AttributeError(name)
# 上文已说到,Local()函数内封装的dict,所以loc实例也是字典
>>> loc = Local()
># 向loc字典添加“foo=42”;
>>> loc.foo = 42
># release_local实际调用local对象的__release_local__方法
># 即释放并删除loc字典中的数据
>>> release_local(loc)
># hasattr() 函数用于判断对象是否包含对应的属性。
># 由于loc字典内的数据被释放,所以foo键不存在;
>>> hasattr(loc, 'foo')
False
>>> ls = LocalStack()
>>> ls.push(42)
>>> ls.top
42
>>> ls.push(23)
>>> ls.top
23
>>> ls.pop()
23
>>> ls.top
42
#———————————————Local设置代理——————————————————————— from werkzeug.local import Local loc = Local() # these are proxies request = loc('request') user = loc('user') #——————————————LocalStack设置代理—————————————————— from werkzeug.local import LocalStack _response_local = LocalStack() # this is a proxy response = _response_local()
loc= Local()
request = LocalProxy(loc, 'request')
request = LocalProxy(get_current_request())
# LocalProxy部分代码 @implements_bool class LocalProxy(object): __slots__ = ('__local', '__dict__', '__name__', '__wrapped__') def __init__(self, local, name=None): object.__setattr__(self, '_LocalProxy__local', local) object.__setattr__(self, '__name__', name) if callable(local) and not hasattr(local, '__release_local__'): # "local" is a callable that is not an instance of Local or # LocalManager: mark it as a wrapped function. object.__setattr__(self, '__wrapped__', local) def _get_current_object(self): '''返回当前对象。如果出于性能原因您一次希望将真实对象放在代理后面, 或者因为要将对象传递到不同的上下文,这将很有用。 ''' ''' 1.由于所有Local或LocalStack对象都有__release_local__ method, \ 所以如果没有该属性就表明self.__local为callable对象。 2.当初始化参数为callable对象时,则直接调用以返回Local或LocalStack对象 ''' if not hasattr(self.__local, '__release_local__'): return self.__local() try: # 此处self.__local为Local或LocalStack对象 return getattr(self.__local, self.__name__) except AttributeError: raise RuntimeError('no object bound to %s' % self.__name__) @property def __dict__(self): try: return self._get_current_object().__dict__ except RuntimeError: raise AttributeError('__dict__') def __getattr__(self, name): if name == '__members__': return dir(self._get_current_object()) return getattr(self._get_current_object(), name) def __setitem__(self, key, value): self._get_current_object()[key] = value def __delitem__(self, key): del self._get_current_object()[key] if PY2: __getslice__ = lambda x, i, j: x._get_current_object()[i:j] def __setslice__(self, i, j, seq): self._get_current_object()[i:j] = seq def __delslice__(self, i, j): del self._get_current_object()[i:j] # 截取部分操作符代码 __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 ''' 重载了绝大多数操作符,以便在调用LocalProxy的相应操作时, 通过_get_current_object method来获取真正代理的对象,然后再进行相应操作 '''
# use Local object directly from werkzeug.local import LocalStack user_stack = LocalStack() # 在堆栈中入栈两个键值对,键都命名为name; user_stack.push({'name': 'Bob'}) user_stack.push({'name': 'John'}) def get_user(): # 出栈这两个键值对(获取user对象) return user_stack.pop() # 直接调用函数获取user对象 user = get_user() # 打印name的value值 print user['name'] print user['name']
John
John
# use LocalProxy
from werkzeug.local import LocalStack, LocalProxy
user_stack = LocalStack()
user_stack.push({'name': 'Bob'})
user_stack.push({'name': 'John'})
def get_user():
# do something to get User object and return it
return user_stack.pop()
# 通过LocalProxy代理user对象
user = LocalProxy(get_user)
print user['name']
print user['name']
John
Bob
[]
操作符用于获取属性),都会重新获取user,从而实现了动态更新user的效果。见下图:Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。