解决方法:Python3中有线程池的实现。使用标准库中concurrent.futures下的ThreadPoolExecutor,对象的submit和map方法可以用来启动线程池中线程执行任务
from concurrent.futures import ThreadPoolExecutor executor=ThreadPoolExecutor(3) ##创建一个Executor对象,指定线程池中有几个线程 ##使用线程池中线程执行任务 def f(a,b): print('f',a,b) return a**b executor.submit(f,2,3) ##调用线程池中线程执行函数,传入函数,及相应参数 ##函数运行结束后,线程归还到线程池,并返回future对象 future.result()##获取线程执行函数的结果 executor.map(f,[2,3,4],[4,5,6]) ##在多个线程上同时调用函数,参数传入列表 ##当线程池中所有线程都在忙碌,再传入一个任务则要等待一个空闲线程才会运行
1234567891011121314151617场景:由于python中GIL的存在,再任意时刻只允许一个线程再解释器中运行。因此python的多线程不适合处理cpu密集型的任务。
想要处理cpu密集型任务,可以采用多进程模型
ps:多个进程则有多个GIL锁,一个进程的多个线程只能一个一个执行
解决方法:使用标准库中multiprocessing.Process 它可以启动子进程执行任务
操作接口,进程间通信,进程间同步等,与Threading.Thread类似
from multiprocessing import Process def f(s):print (s) Process(target=f,args=('hello',)) p.start() ##启动进程 p.join() #等待进程的结束 x=1 def g(): global x x=5 p=Process(target=f) p.start() x >1 ##可见子进程和主进程是独立的,x是不一样的 ##进程间如何进行通信 from multiprocessing import Queue,Pipe q=Queue() def f(q): print('start') print(q.get()) ##获取队列的值 print('end') Process(target=f,args=(q,)).start() >start q.put(100) >100 >end c1,c2=Pipe() ##创建双向的管道 c1.send('abc') ##由c1端写入的数据要从c2端读取 c2.recv()##同理,由c2端写入的数据要从c1端读取 def f(c): c.send(c.recv()*2) c1,c2=Pipe() Process(target=f,args=(c2,)).start() c1.send(55) ##执行了c.recv()*2 c2.recv() ##执行了c.send() >110
1234567891011121314151617181920212223242526272829303132333435363738394041424344科普:水仙花数(Narcissistic number)也被称为阿姆斯特朗数(Armstrong number),水仙花数是指一个 3 位数,它的每个位上的数字的 3次幂之和等于它本身(例如:1^3 + 5^3+ 3^3 = 153)。
##cpu密集型任务:多进程多线程,寻找水仙花数 from threading import Thread from multiprocessing import Process def isArmstrong(n): ##判断水仙花数 a,t=[].n while t>0: a.append(t%10) t /=10 k=len(a) return sum(x**k for x in a)==n def findArmstrong(a,b): ##在某一范围查找水仙花数 print(a,b) res=[k for k in range(a,b) if isArmstrong(k)] print('%s-%s:%s'%(a,b,res) def findByThread(*argslist): ##使用多线程 workers=[] for args in argslist: worker=Thread(target=findArmstrong,args*=args) workers.append(worker) worker.start() for worker in workers: worker.join() def findByProcess(*argslist): workers=[] for args in argslist: worker=Process(target=findArmstrong,args=args) workers.append(worker) worker.start() for worker in workers: worker.join() if __name__=='__main__': import time start=time.time() findByProcess((2000000,2500000),(2500000,300000)) ##进程花费15秒多 findByThread((2000000,2500000),(2500000,300000)) ##cpu利用不到100%,线程花费40秒多 print(time.time()-start)
123456789101112131415161718192021222324252627282930313233343536373839场景:为多个函数统一添加某种功能,不用一一添加相同代码。比如计时统计,记录日志,缓存运算结果等等
解决方案:定义装饰器函数,用它来生成一个在原函数基础添加了新功能的函数,代替原函数
##设计一个装饰器解决重复计算子问题的例子(减少重复计算): ##用缓存记录之前的计算结果,在每一次计算前检查以前的运算是否可以拿来利用 def memo(func): cache={} def wrap(*args): if args not in cache: cache[args]=func(*args) return cache[args] return wrap ##题目一:斐波那契数列:指的是1,1,2,3,5,8,13,21... ##这个数列从第三项开始,每一项都等于前两项之和,求数列第n项 @memo ##等价于fibonacci=memo(fabonacci) def fibonacci(n): if n <= 1: return 1 return fibonacci(n-1)+fibonacci(n-2) ##题目二:一个共有10个台阶的楼梯,从下面追到上面,一次只能迈 ##1-3个台阶,并且不能后退,走完这个楼梯共有多少种方法。(回溯法问题) @memo def climb(n,step): count=0 if n==0: count=1 elif n>0: for step in steps: count+=climb(n-step,steps) return count climb(10,(1,2,3))
12345678910111213141516171819202122232425262728293031323334在函数对象中保存这一些函数的元数据,例如
f.__name__:函数的名字
f.__doc__:函数文档字符串
f.__moudle__:函数所属模块名
f.__dict__:属性字典
f.__defaults__:默认参数元组
我们在使用装饰器后,再使用上面这些属性访问时,看到的是内部包裹函数的元数据,原来函数的元素据便丢失掉了
解决方法:使用标准库functools中的装饰器wraps装饰内部包裹函数,可以 制定将原函数的某些属性,更新到包裹函数上面
def f(): '''f function''' ##定义文档字符串 a=2 return a*2 ##举例 f.__name__ >'f' f.__doc__ >'f function' f.__module__ >'__main__' def mydecirator(func): def wrapper(*args,**kargs): '''wrapper function''' print('In wrapper') func(*args,**kargs) return wrapper ## @mydecorator def example(): '''example function''' print('In example') ##在没有装饰器的情况下 example.__name__ >'example' example.__doc__ >'example function' ##在有装饰器的情况下 ##example.__name__ ##>'wrapper' ##example.__doc__ ##>'wrapper function'
12345678910111213141516171819202122232425262728293031323334353637##修改后 from functools import updata_wrapper,wraps def mydecirator(func): ##@wraps(func) ##最简单,直接使用装饰器 def wrapper(*args,**kargs): '''wrapper function''' print('In wrapper') func(*args,**kargs) updata_wrapper(wrapper,func,('__name__','__doc__'),('__dict__',)) ##将原函数的属性更新到包裹函数当中 ##参数分别是包裹函数,被包裹函数,替换的元数据,合并的元数据 ##后两项参数的默认值分别为('__module__'__name__','__doc__'),('__dict__') return wrapper @mydecorator def example(): '''example function''' print('In example') example.__name__ >'example' example.__doc__ >'example function'
1234567891011121314151617181920212223相关知识
SKYNE/python
python 花卉识别系统 用python搭建一个花卉识别系统(IT技术)
python利用c4.5决策树对鸢尾花卉数据集进行分类(iris)
Python机器学习基础教程
利用KNN对150个实例对花卉进行机器培训
python基础语法花多长时间
python绘制花
使用Python调用mysql
用python画花瓣
用Python做兼职,轻松赚取零花钱,分享Python兼职经验
网址: Python实例(六) https://m.huajiangbk.com/newsview112815.html
上一篇: 鲜花只能做装饰?错!鲜花养生功效 |
下一篇: jeesite |