Flask上下文管理源码剖析(储备知识)

一. 偏函数

import functools


def index(a1,a2):
    return a1 + a2

# 原来的调用方式
# ret = index(1,23)
# print(ret)

# 偏函数,帮助开发者自动传递参数
new_func = functools.partial(index,666)
ret = new_func(1)
print(ret)

二. 执行父类的方法

"""
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()
"""
####################################
class Base(object):

    def func(self):
        super(Base, self).func()
        print('Base.func')

class Bar(object):
    def func(self):
        print('Bar.func')

class Foo(Base,Bar):
    pass

# 示例一
# obj = Foo()
# obj.func()
# print(Foo.__mro__)

# 示例二
# obj = Base()
# obj.func()

三. 面向对象的特殊方法

class Foo(object):
    def __init__(self):
        # self.storage = {}
        object.__setattr__(self,'storage',{})  #调用父类的__setattr__方法

    def __setattr__(self, key, value):
        print(key,value,self.storage)

obj = Foo()
obj.xx = 123   ##对象会自动调用__setattr__方法

四. 栈

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('神1')
_stack.push('神2')

print(_stack.pop())
print(_stack.pop())

五. threading.local详解

多线程中,线程间的数据是共享的, 但是每个线程想要有自己的数据该怎么实现? python中的threading.local对象已经实现,其原理是利用线程的唯一标识作为key,数据作为value来保存其自己的数据,以下是demo演示了多个线程同时修改同一变量的值的结果

实现一个多线程demo

import threading
from threading import local
import time

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()

那么问题来了,我们如何获取一个线程的唯一标记?threading.get_indet()来获取,根据字典自定义一个为每个协程开辟空间进行存取数据。

import time
import threading
import greenlet

DIC = {}

def task(i):

    # ident = threading.get_ident()   #这是用get_ident来标记线程
    ident = greenlet.getcurrent()     #这是用协程来表现
    if ident in DIC:
        DIC[ident]['xxxxx'] = i
    else:
        DIC[ident] = {'xxxxx':i }
    time.sleep(2)

    print(DIC[ident]['xxxxx'],i)

for i in range(10):
    t = threading.Thread(target=task,args=(i,))
    t.start()

 加强版的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()

为什么说是加强版的threading.local呢?首先代码中先用协程来做数据隔离,如果协程报错再用线程来进行数据隔离。用协程进行数据隔离避免了上下文切换节省

了开销,如果协程报错,在用线程来隔离,这个也实现代码的健壮性。

 

posted @ 2018-12-21 19:37  Jacob先生  阅读(134)  评论(0)    收藏  举报