一 上下文管理 前戏知识点 local 和 偏函数 面向对象 栈
1. local
local多个线程修改同一个数据,复制多份变量给每个线程用,
比如我们用的request,怎样让不同的请求有自己的request。就是为每个线程开辟一块空间进行数据存储
threading.local【和flask无任何关系】
作用:为每个线程创建一个独立的空间,使得线程对自己的空间中的数据进行操作(数据隔离)。
不用threading.local
from threading import Thread import time ctx = -1 def task(arg): global ctx ctx = arg # time.sleep(2) print(ctx) for i in range(5): t = Thread(target=task,args=(i,)) t.start() # 0 # 1 # 2 # 3 # 4
使用threading.local
from threading import Thread,local # 特殊的对象 ctx = local() def task(arg): ctx.value = arg # time.sleep(2) print(ctx.value) for i in range(5): t = Thread(target=task,args=(i,)) t.start() # 0 # 1 # 2 # 3 # 4
import threading from threading import local def task(i): print(threading.get_ident(),i) # 获取每个线程唯一id for i in range(5): t = threading.Thread(target=task,args=(i,)) t.start() # 14896 0 # 10780 1 # 3356 2 # 11384 3 # 14308 4
import threading from threading import local import time obj = local() def task(i): obj.xxxxx = i print(threading.get_ident(), obj.xxxxx,"拉拉") time.sleep(2) # print(obj.xxxxx,i) print(threading.get_ident(),i,"哈哈") for i in range(5): t = threading.Thread(target=task,args=(i,)) t.start() # 6232 0 拉拉 # 4348 1 拉拉 # 7084 2 拉拉 # 972 3 拉拉 # 6560 4 拉拉 # 6232 0 哈哈 # 6560 4 哈哈 # 972 3 哈哈 # 4348 1 哈哈 # 7084 2 哈哈
通过字典自定义threading.local(函数) 方法一
根据字典自定义一个为每个协程开辟空间进行存取数据。
import time import threading import greenlet DIC = {} def task(i): # ident = threading.get_ident() ident = greenlet.getcurrent() if ident in DIC: DIC[ident]['aa'] = i else: DIC[ident] = {'aa':i } time.sleep(2) print(DIC[ident]['aa'],i) for i in range(5): t = threading.Thread(target=task,args=(i,)) t.start() print(DIC)
面向对象版
from threading import Thread,get_ident class Local(object): storage = {} def get(self,k): ident = get_ident() return Local.storage[ident][k] def set(self,k,v): ident = get_ident() if ident in Local.storage: Local.storage[ident][k] = v else: Local.storage[ident] = {k:v} obj = Local() def task(arg): obj.set('val',arg) v = obj.get('val') print(v) for i in range(10): t = Thread(target=task,args=(i,)) t.start()
兼容线程和协程(源码到request中去看,看local的__getattr__,setattr)
- 通过getattr/setattr 构造出来 threading.local的加强版(协程)
import time import threading try: import greenlet get_ident = greenlet.getcurrent except Exception as e: get_ident = threading.get_ident class Local(object): DIC = {} def __getattr__(self, item): ident = get_ident() if ident in self.DIC: return self.DIC[ident].get(item) return None def __setattr__(self, key, value): ident = get_ident() if ident in self.DIC: self.DIC[ident][key] = value else: self.DIC[ident] = {key:value} obj = Local() def task(i): obj.xxxxx = i time.sleep(2) print(obj.xxxxx,i) for i in range(10): t = threading.Thread(target=task,args=(i,)) t.start()
2. 偏函数(functoots.partial)
import functools def index(a1,a2): return a1 + a2 # 原来的调用方式 # ret = index(1,23) # print(ret) # 偏函数,帮助开发者自动传递参数 new_func = functools.partial(index,5) ret = new_func(1) print(ret)
3.面向对象 执行父类方法 和 面向对象中特殊的方法
class Base(object): def func(self): print('Base.func父亲') class Foo(Base): def func(self): # 方式一:根据mro的顺序执行方法 # super(Foo,self).func() # 方式二:主动执行Base类的方法 Base.func(self) print('Foo.func儿子') obj = Foo() obj.func() # Base.func父亲 # Foo.func儿子
class Base(object): def func(self): super(Base, self).func() print('Base.func') class Bar(object): def func(self): print('Bar.func1111111') class Foo(Base,Bar): pass # 示例一 obj = Foo() obj.func() print(Foo.__mro__) # Bar.func1111111 # Base.func # (<class '__main__.Foo'>, <class '__main__.Base'>, <class '__main__.Bar'>, <class 'object'>) # 示例二 报错没有这个方法 AttributeError: 'super'对象没有属性'func' # obj = Base() # obj.func()
class Foo(object): def __init__(self): # self.storage = {} object.__setattr__(self,'storage',{}) def __setattr__(self, key, value): print(key,value,self.storage) obj = Foo() obj.xx = 123
# xx 123 {}
__getitem__ __setitem__ __delitem__
class Foo(object): def __getitem__(self, item): print(item,"11") def __setitem__(self, key, value): print(key,value,"22") def __delitem__(self, key): print(key,"333") obj = Foo() obj['k1'] obj["aa"] obj['k1'] = 123 del obj['k1'] # k1 11 # aa 11 # k1 123 22 # k1 333
class Test(object): def __init__(self ,name): self.name = name def __getattr__(self, value): if value == 'address': return 'China111' if __name__=="__main__": test = Test('letian') print (test.name) print (test.address) test.address = 'Anhui' print (test.address) # letian # China111 # Anhui # 如果是调用了一个类中未定义的方法,则__getattr__也要返回一个方法,例如: class Test(object): def __init__(self, name): self.name = name def __getattr__(self, value): return len if __name__ == "__main__": test = Test('letian') print( test.getlength('letian')) # 6
isinstance===>>>MethodType和isinstance和Type函数 def func(): pass class Foo(object): def func(self): pass # 执行方式一 # obj = Foo() # obj.func() # 方法 # 执行方式二 # Foo.func(123) # 函数 from types import FunctionType,MethodType # 通过实例化方法 func是一个方法 obj = Foo() print(isinstance(obj.func,FunctionType)) # False print(isinstance(obj.func,MethodType)) # True # 通过类名判断 func 是函数 不是方法 print(isinstance(Foo.func,FunctionType)) # True print(isinstance(Foo.func,MethodType)) # False
__slots__ class Foo(object): # __slots__ = ('name',) def __init__(self): self.name = '111' self.age = 18 obj = Foo() print(obj.name) print(obj.age) # 111 # 18 class Foo(object): __slots__ = ('name',) def __init__(self): self.name = 'alex' # self.age = 18 obj = Foo() print(obj.name) # print(obj.age) # 111
# by luffycity.com DATA = { 'request': { 'method': "GET", 'form': {} }, 'session': { 'user': '哈哈哈哈', 'age': "19" } } class LocalProxy(object): def __init__(self, key): self.key = key def get_dict(self): return DATA[self.key] def __str__(self): return 'asdf' def __getattr__(self, item): data_dict = self.get_dict() aa=111 return data_dict[item],aa def __getitem__(self, item): data_dict = self.get_dict() return data_dict[item] def __add__(self, other): return other + 1 request = LocalProxy('request') session = LocalProxy('session') print(request.method) print(request.form) print(session.user) print(session.age) 执行: # ('GET', 111) # ({}, 111) # ('哈哈哈哈', 111) # ('19', 111) # Process finished
class Foo(object): def __str__(self): return 'asdf' def __getattr__(self, item): return "999" def __getitem__(self, item): return '87' def __add__(self, other): return other + 1 obj = Foo() print(obj) print(obj.x) print(obj['x1']) print(obj + 7) 执行: asdf 999 87 8
4. 栈
class Stack(object): def __init__(self): self.data = [] def push(self,val): self.data.append(val) def pop(self): return self.data.pop() def top(self): return self.data[-1] _stack = Stack() _stack.push('李四') _stack.push('王五') print(_stack.pop()) print(_stack.pop()) #王五 #李四