深圳市工程建设交易服务中心网站,建站之星设计师,重庆微网站,wordpress设置首页title1. 说在前面#xff1a;从“能跑”到“跑得快” 兄弟们#xff0c;如果你前面的 5 讲都跟下来了#xff0c;那你已经能写出解决大部分业务逻辑的代码了。 但现实世界是很残酷的#xff1a; 你的程序要处理 10 万张图片的下载#xff0c;难道要一张一张排队等吗#xf…1. 说在前面从“能跑”到“跑得快”兄弟们如果你前面的 5 讲都跟下来了那你已经能写出解决大部分业务逻辑的代码了。但现实世界是很残酷的你的程序要处理 10 万张图片的下载难道要一张一张排队等吗你的程序要从几万行日志里找出所有的手机号难道要用if一行行判断吗这一讲我们要聊聊 Python 的**“高级外挂”**并发编程、正则表达式。学完这一讲你的代码将从“能跑”进化到“跑得快、写得骚”。2. 并发编程别让你的 CPU 闲着很多新手分不清“多线程”、“多进程”和“协程”。咱们用大白话讲清楚。2.1 多线程 (Threading)一个厨房多个厨师适合**“等人”**的任务I/O 密集型比如下载文件、读写数据库。importthreadingimporttimedeftask(name):print(f任务{name}开始...)time.sleep(2)# 模拟耗时操作print(f任务{name}完成)# 创建线程t1threading.Thread(targettask,args(A,))t2threading.Thread(targettask,args(B,))t1.start()t2.start()t1.join()# 等它执行完t2.join()避坑指南因为 Python 有个叫GIL全局解释器锁的玩意儿多线程没法利用多核 CPU。所以如果是算力任务比如视频转码多线程反而可能变慢。2.2 多进程 (Multiprocessing)开多个分店适合**“算数”**的任务CPU 密集型。每个进程有自己独立的内存能真正利用多核。2.3 协程 (Asyncio)时间管理大师这是现代 Python 的宠儿。它不切换线程而是利用等待时间去干别的活。importasyncioasyncdefsay_hello():print(你好...)awaitasyncio.sleep(1)# 异步等待print(世界)# 运行asyncio.run(say_hello())老司机建议全栈开发里写爬虫或者高性能 Web 服务asyncio是必修课。3. 正则表达式字符串处理的“终极武器”如果你要在一万行文本里找邮箱地址用split()和find()会写死人的。3.1 常用符号速记\d匹配数字Digital\w匹配字母、数字、下划线Word匹配 1 次或多次*匹配 0 次或多次?匹配 0 次或 1 次贪婪 vs 非贪婪的关键3.2 实战验证手机号importre phone_patternr^1[3-9]\d{9}$test_num13812345678ifre.match(phone_pattern,test_num):print(这是个合法的手机号)else:print(手机号格式不对。)4. 高级特性迭代器与生成器4.1yield节省内存的神如果你要生成一百万个数千万别用return list。defmy_range(n):i0whilein:yieldi# 停在这里下次再来i1# 它不会一次性把 n 个数存进内存forxinmy_range(1000000):ifx10:breakprint(x)直白解释yield就像是食堂的大妈你拿个碗去领饭她给你一勺你再去她再给你一勺。她不需要提前做出一万份饭堆在桌子上。5. 综合实战简易异步网页扫描器咱们结合asyncio和re写一个能并发扫描多个链接并提取标题的工具。importasyncioimportre# 模拟一个异步下载函数asyncdeffetch_page(url):print(f正在下载{url})awaitasyncio.sleep(1)# 模拟网络延迟# 模拟网页内容returnfhtmltitle这是{url}的标题/title/htmlasyncdefscan_url(url):htmlawaitfetch_page(url)# 用正则抓取标题titlere.search(rtitle(.*?)/title,html)iftitle:print(f【抓取成功】{url}-{title.group(1)})asyncdefmain():urls[http://python.org,http://csdn.net,http://github.com]# 并发运行awaitasyncio.gather(*(scan_url(url)forurlinurls))if__name____main__:starttime.time()asyncio.run(main())print(f总耗时{time.time()-start:.2f}s)6. 避坑小贴士老司机的叮嘱别被正则搞疯了正则虽然强大但很难读。如果你写的正则超过三行请考虑用BeautifulSoup爬虫库或者多写几个if。并发不是越快越好开太多的线程或进程会把电脑拖死。要根据 CPU 核心数和内存来合理控制。async/await必须配套你在一个async函数里用了同步的time.sleep()整个程序都会卡住。必须用asyncio.sleep()。6. 实战演练巩固你的内功题目 1多线程下载器需求模拟一个多线程下载器。有一个 URL 列表urls [url1, url2, url3, url4, url5]。使用concurrent.futures.ThreadPoolExecutor开启 3 个线程并发下载用time.sleep(1)模拟下载耗时。打印每个任务的开始和结束时间。点击查看参考答案importtimefromconcurrent.futuresimportThreadPoolExecutordefdownload(url):print(f开始下载{url})time.sleep(1)# 模拟网络请求print(f下载完成{url})returnf{url}-contenturls[furl-{i}foriinrange(1,6)]# 使用 ThreadPoolExecutor 管理线程池# max_workers3 表示同时最多有 3 个线程在跑start_timetime.time()withThreadPoolExecutor(max_workers3)asexecutor:executor.map(download,urls)print(f全部任务结束耗时{time.time()-start_time:.2f}秒)题目 2正则提取与替换需求给定一段乱糟糟的文本text 联系我zhangsan163.com 或者 lisi_2023gmail.com电话13800138000提取出所有的邮箱地址。把所有的邮箱地址替换成[隐藏邮箱]。点击查看参考答案importre text联系我zhangsan163.com 或者 lisi_2023gmail.com电话13800138000# 1. 提取邮箱# \w 匹配字母数字下划线 匹配 符号\. 匹配点email_patternr\w\w\.\wemailsre.findall(email_pattern,text)print(f找到的邮箱{emails})# 2. 替换邮箱hidden_textre.sub(email_pattern,[隐藏邮箱],text)print(f脱敏后的文本{hidden_text})题目 3生成器斐波那契数列需求编写一个生成器函数fib(n)生成斐波那契数列的前 n 项。斐波那契数列0, 1, 1, 2, 3, 5, 8…后一项等于前两项之和。使用for循环打印前 10 项。点击查看参考答案deffib(n):a,b0,1count0whilecountn:yielda# 每次暂停并返回 aa,bb,ab count1# 使用生成器fornuminfib(10):print(num,end )print()# 换行7. 系列索引上一篇第5讲 | 异常处理、文件 IO 与项目实战构建你的第一个生产级工具下一篇第7讲 | 数据库集成让你的数据在 MySQL 与 MongoDB 中安家写在最后这一讲的内容非常硬核。如果你能理解asyncio的调度逻辑和yield的节省内存大法你已经半只脚踏入高级开发的门槛了。别只是看去跑一下那个异步扫描器的代码。感受一下原本需要 3 秒的任务在异步下不到 1 秒就跑完的快感。觉得有收获的话点赞、收藏咱们下一讲聊聊怎么把数据存进真正的数据库