flask上下文基础
面向对象双下划线方法
首先,先来聊一聊面向对象中的一些特殊的双下划线方法,比如__call__、__getattr__系列、__getitem__系列。
__call__
在单例模式中,我们可能用到过,除此之外,还想就没有在什么特殊场景中用到了。我们往往忽视了它一个很特殊的用法:对象object+()或者类Foo()+()这种很特殊的用法。在Flask上下文管理中,入口就是使用了这种方式。
__getitem__系列
使用这个系列的方法时,我们最大的印象就是调用对象的属性可以像字典取值一样使用中括号([])。使用中括号对对象中的属性进行取值、赋值或者删除时,会自动触发对应的__getitem__、__setitem__、__delitem__方法。
foo["age"] = 18 调用__setitem__ print(foo["age"]) 调用__getitem__ del foo["age"] 调用__delitem__
__getattr__系列
使用对象取值、赋值或者删除时,会默认的调用对应的__getattr__、__setattr__、__delattr__方法。
对象取值时,取值的顺序为:先从__getattribute__中找,第二步从对象的属性中找,第三步从当前类中找,第四步从父类中找,第五步从__getattr__中找,如果没有,直接抛出异常。
foo.age = 18 调用__setattr__ print(foo.age) 调用__getattr__ del foo.age 调用__delattr__
偏函数
python中有一个小工具包functools,这个包中包含了几个在很有用的小功能,比如:wraps:在使用装饰器时,使用这个方法可以保护函数的元信息。reduce:一个合并序列项为一个单一值的小方法。还有一个就是偏函数: partial
一句话来总结partial的作用,固定函数中的一些参数,返回一个新的函数,方便调用
from functools import partial
def ab(a,b):
print(a,b)
return a+b
par_ab = partial(ab,1) # 把 1 传给 a
print(par_ab)
print(par_ab(2)) # 把 2 传给 b
输出:
functools.partial(<function ab at 0x0000000002122E18>, 1)
1 2
3
threading.local
在多线程中,同一个进程中的多个线程是共享一个内存地址的,多个线程操作数据时,就会造成数据的不安全,所以我们就要加锁。但是,对于一些变量,如果仅仅只在本线程中使用,怎么办?
方法一,可以通过全局的字典,key为当前线程的线程ID,value为具体的值。
方法二,使用threading.local方法
threading.local 在多线程操作时,为每一个线程创建一个值,使得线程之间各自操作自己的值,互不影响。
import time
import threading
from threading import local
class Foo(local):
pass
foo = Foo()
def add(i):
foo.num=i
time.sleep(1)
print(foo.num,i,threading.current_thread().ident) # 第三个参数是,线程id
for i in range(20):
th = threading.Thread(target=add,args=(i,))
th.start()
flask与其他python框架比如(Django、tornado)在整个请求生命周期中对于数据的管理机制的不同。django、tornado是通过传参的形式传递数据,而flask是通过其特有的上下文管理机制来管理数据的。
在flask中,上下文管理机制分为两个大的部分:请求上下文和应用上下文。

浙公网安备 33010602011771号