先来一个比较low的回调函数示例,这里简单说下,回调其实就是一个对象,这个对象能够实例化那么我们就说可以回调,也就是简单的(*args,*kwargs)调用了
def click(func,*args,**kwargs):
func()
print 'callback over'
def callback():
time.sleep(1)
print 'i am callback'
click(callback)
运行结果如下:
i am callback
callback over
OK,这就如同一个button触发一个event似的,不过问题在于,这是同步的啊,我居然硬生生等了1S。。。这有啥意义呢,纯粹就是为了少写几个button,把所有的event当参数传递进去,一个最low的封装而已。好吧,我们现在考虑考虑如何异步执行吧
直接上代码吧:
import time
import threading
def click(func,*args,**kwargs):
func
print 'callback over'
def callback():
time.sleep(3)
print 'i am callback'
def anc(func):
t = threading.Thread(target=func,args=())
t.start()
t.join()
click(anc(callback))
结果如下:
i am callback
callback over
结果我们依然等了3S,你以为重新开一个线程,我就不会等你了吗?
我们继续改进下呢
import time
import threading
def click(func,*args,**kwargs):
func
print 'callback over'
def callback():
time.sleep(3)
print 'i am callback'
def anc(func):
t = threading.Thread(target=func,args=())
t.start()
# t.join() 这玩意好像引起阻塞了,我们去掉吧
click(anc(callback))
结果如下:
callback over
>>> i am callback
OK,这下没问题了,我们让我们的主线程开心的跑它的,子线程还在忙就忙它的呗,反正到时候,正常情况我们是去调别人的一个api,把我们的结果返回给它。。。很好。这下完美了。
下面问题来了,这样看上去是不是让你们觉得有点不高大上,每次调用都显得非常的麻烦,没问题,我们继续优化,是时候让我们的装饰器登场了。
import time
import threading
import threading
import time
def callback(func):
def wrapper(*args, **kwargs):
t = threading.Thread(target=func,args=())
t.start()
return wrapper
def click(func,*args,**kwargs):
func()
print "callback maybe not end,but i need tell him that i've received his command"
@callback
def event():
time.sleep(5)
print 'i am a event what you need now!'
@callback
def another_event():
time.sleep(2)
print 'i am another event you need now!'
click(event)
click(another_event)
执行结果如下:
callback maybe not end,but i need tell him that i've received his command
callback maybe not end,but i need tell him that i've received his command
1213
>>> i am another event you need now!
i am a event what you need now!
>>>
OK,现在是不是就完美多了,更加的pythonic了!
现在新的问题来了,如果是在一个类里面呢?
同学们,你们需要思考一下了:
1 不同的线程,我们的私有变量应该如何去处理;
2 如果返回的是实时数据,我们应该如何避免管道阻塞的问题。
这一节我就不做深入讨论了,下一章讲解WSGI的api开发的时候我们再来讲解吧