尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Python 学习日志(8.25)

Python 学习日志(8.25) 文章目录Python 学习日志8.25一、Match 结构模式匹配为什么是方括号而不是圆括号然后拆成三块来看如果需要元组怎么办二、for in 循环三、while 循环四、切片五、作业利用循环打印 Hello, xxx!六、[] 与 None 的区别七、break 与 for 循环踩坑八、for 还是 while一句话判断法九、continuePython 学习日志8.25学习教程廖雪峰的 Python 教程 - match一、Match 结构模式匹配Ok啊朋友们今天来学习 match。Match 和 if else 是一样的但是场景略有区别普通的逻辑判断更加适合使用 if elsematch 更加适合使用在提取固定元素上。例如以下例子a10b10ifa5:print(a5)elif5a10:print(f{a})matchb:case5:print(b5)case6|7:print(b6)case8:print(b7)casexifx9:print(b9)case_:print(b8)会输出10 b8这个代码写的比较简单实际上就是这样的一个代码commandinput(请输入指令)matchcommand:casestart:print(开始运行)casestop:print(停止运行)caserestart:print(重启)case_:print(未知指令)其中match command:—— 说我要判断 command 这个变量case start:—— 说如果 command 的值是 ‘start’就执行下面的代码case _:—— 这个下划线是通配符意思是以上都不是的话就执行这个就像 if 里的 elseCase 写起来比 if else 更加清晰直观。然后是老师教程里面的示例代码args[gcc,hello.c,world.c]# args [clean]# args [gcc]matchargs:# 如果仅出现gcc报错:case[gcc]:print(gcc: missing source file(s).)# 出现gcc且至少指定了一个文件:case[gcc,file1,*files]:print(gcc compile: file1, , .join(files))# 仅出现clean:case[clean]:print(clean)case_:print(invalid command.)可能有的同学看不懂没关系这很正常match 就是一个结构模式匹配下面来详细讲讲。args 是一个列表里面有 3 个元素。match 的任务就是根据列表的形状决定执行哪段代码。再看四个 case按顺序从上往下试case它要求列表长什么样现在能匹配吗[gcc]只有 1 个元素且是 ‘gcc’❌ 你的列表有 3 个元素[gcc, file1, *files]第 1 个是 ‘gcc’后面至少还有 1 个剩下的都塞给 files✅ 匹配[clean]只有 1 个元素且是 ‘clean’❌ 第 1 个是 ‘gcc’ 不是 ‘clean’_啥都行兜底—— 不会走到这前面已经匹配了为什么是方括号而不是圆括号同学们最难理解的可能是这一行case [gcc, file1, *files]:首先第一个为什么是方括号不应该是圆括号吗因为匹配的 args 是一个列表args [gcc, hello.c, world.c]所以需要用方括号如果变成圆括号case 就不会匹配到列表而是去匹配元组例如args[gcc,hello.c]# 这是个列表 listmatchargs:case[gcc,hello.c]:# 方括号 列表模式要求 args 必须是列表print(我匹配了列表)case(gcc,hello.c):# 圆括号 元组模式要求 args 必须是元组print(我匹配了元组)会输出我匹配了列表所以这里要使用方括号。然后拆成三块来看然后是第二个拆成三块gcc—— 固定要求第 1 个元素必须是 ‘gcc’file1—— 变量名接住第 2 个元素也就是 ‘hello.c’*files—— 星号的意思和函数参数里的*args一样是把剩下的所有元素都收进这个列表所以当args [gcc, hello.c, world.c]时相当于自动做了这样一件事, .join(files)是把列表里的元素用逗号拼起来比如[a,b,c]会变成a, b, c。gcc → 检查通过 file1 hello.c files [world.c] # 剩下的都装进来变成一个列表注意这里的 file1 和 files 都是变量名字不是特殊写法可以写成case[gcc,file1,*files]:# 可以case[gcc,file1,*rest]:# 也可以case[gcc,file1,*others]:# 都行第二个 file1 意思是有一个 file1 —— 变量名接住第 2 个元素也就是 ‘hello.c’。第三个 *files 是将后面的所有东西都打包装进 files 这个列表里面甚至如果你不关心后面的是什么也可以写成case[gcc,file1,*_]:# 只要开头是 gcc 加一个文件剩下的不管如果需要元组怎么办然后就是有同学问如果需要元组怎么办很简单直接转换一下就行case[gcc,file1,*files]:filestuple(files)# 匹配完之后手动转一下# files (b.c,)另外*_不会变成列表它不会给任何变量赋值所以也不会产生一个绑定名字的列表。就像你打包快递*files是把剩下的装进袋子袋子叫 files*_是剩下的我直接扔了袋子也不留。二、for in 循环然后是循环先说 for in直接看代码a[abc,bcd,cad]forbina:print(b)sum0forxin[1,2,3,4,5,6,7,8,9,10]:sumsumxprint(sum)For 后面的变量名 a 就像一个快递员每次从列表里从左到右取一个元素取到后就执行缩进里的语句执行完再去取下一个直到列表取完。另外这里注意缩进如果 print 是在缩进里面就会输出多次如果是在外面就会在 for 循环执行完了才会输出不只是列表元组、字符串、range 都能依次取元素。额外的小知识foriinrange(5):# range(5) 就是 [0, 1, 2, 3, 4]print(i)Range 是范围从 0 开始到指定个元素结束。三、while 循环然后就是 while当条件不满足就一直执行。直接看代码c0n99whilen0:ccn nn-2print(c)会输出2500n 初始 99while 后面变量 n 大于 0于是开始执行代码直到每次 n 被减 2 越来越小当 n 小于 0 时不满足 n 大于 0 的条件于是 while 结束并 print 结果。同样的n 是一个变量所以也可以不只是数字但是请注意 while 循环的条件如果是比大小这些需要数字运算的n 只能是数字如果是n ! 那 n 也可以是字符串。例如texthellowhiletext!:# 只要 text 不是空字符串就继续print(当前字符串是:,text)texttext[1:]# 每次砍掉第一个字符print(循环结束text 变成空字符串了)text[1:]的意思是从第 2 个字符开始取到末尾所以每次 text 都会少一个字符最后变成空字符串。当text 时 ! 为假循环就停了。四、切片text[1:]的这个写法是切片是一个常用的截取字符串的操作texthello# 位置: h0 e1 l2 l3 o4标准格式是text[start:end]# start 从哪开始包含# end 到哪结束不包含写个表格更加直观写法含义对 “hello” 的结果text[1:]从 1 到末尾ellotext[:3]从开头到位置 3不含heltext[1:3]从 1 到 3不含eltext[:]全部hellotext[::2]隔一个取一个hlotext[::-1]倒过来olleh进阶版是text[起点:终点:步长]text[::2]—— 第三个参数是步长每次走几步text[::2]的意思是从头开始每次往后跳 2 步位置: 0 1 2 3 4 字符: h e l l o ↑ ↑ ↑ 第1步 第2步 第3步 (跳2格) (再跳2格) 取到的h → l → o 结果 hlotext[::-1]—— 步长是负数表示倒着走text[::-1]的意思是从最后一个位置开始每次往回走 1 步位置: 0 1 2 3 4 字符: h e l l o ↑ ← ← ← ← 4 → 3 → 2 → 1 → 0 取到的o → l → l → e → h 结果 olleh步长 -1 就是方向反过来每次走 1 步所以从尾部一路取到头部整个字符串就倒过来了。顺带一提步长还可以和起止位置组合text[1:4:2] → 从位置1到位置4不含每次跳2步 位置1是e跳2步到位置3是l → el切片的完整公式就是text[起点:终点:步长]—— 起点决定从哪开始终点决定到哪停步长决定怎么走。五、作业利用循环打印 Hello, xxx!老师的作业是L[Bart,Lisa,Adam]# 请利用循环依次对list中的每个名字打印出Hello, xxx!那么可以这样写L[Bart,Lisa,Adam]foriinL:print(i)或者用 while 可以写whileL![]:xL.pop(0)# 取出最前面的元素同时删除它print(fHello,{x}!)print(空列表,L)但其实这里有个问题就是while L ![]:实际上会永远判定为真空列表是[]而[]表示列表里面有一个空的字符串所以实际上代码应该是whileL![]:# while L: L非空就继续空了就停xL.pop(0)# 取出最前面的元素同时删除它print(fHello,{x}!)print(空列表,L)六、[] 与 None 的区别这里我相信很多同学分不清空的区别是不是觉得 [] 等于 None实际上是这样的[]不等于None但它们有一个共同点在判断真假时都算假。[] 是空列表一个容器只是里面没有东西None 是什么都没有Python 里表示空的特殊值。执行print([]None)# False不等于会输出 False。一个是空的盒子一个是根本没有盒子所以它们不相等。但是它们在真假判断里都是假Python 里每个值都可以当真/假用这叫 truthy/falsy常见的假值有值是啥当条件用时[]空列表假 ❌空字符串假 ❌0数字零假 ❌None什么都没有假 ❌False布尔假假 ❌所以回到我们的的 whilewhileL:# 等价于 while L 不是假值L 是[]时条件为假循环停——这跟 None 没关系纯粹是因为空列表是假值。再区分一下等于和真假print([]None)# False不相等print(bool([]))# False但判断真假时是假print(bool(None))# False判断真假时也是假一句话总结[] 和 None 不是一回事但它在 while/if 里都和 None 一样算假。我们写while L:的时候其实就是在说只要 L 不是假的非空就继续七、break 与 for 循环踩坑然后是 break执行到某一个阶段就可以在 if 下面使用 break。例如n1whilen100:ifn10:# 当n 11时条件满足执行break语句break# break语句会结束当前循环print(n)nn1print(END)实际上也可以试试用 for in 写然后你就会发现踩坑了因为你大概率会写成这样L[Bart,Lisa,Adam]foriinL:iflen(L)0:xL.pop(0)# 取出最前面的元素同时删除它print(fHello,{x}!)else:breakprint(END)print(fHello, Adam!)实际上运行一下你会发现 Adam 消失了所以不得不使用 print 保底输出这是为什么呢因为 for in 里面取循环不是想象的对应取Python 的for i in L:并不是依次把元素给你而是内部偷偷用一个计数器索引从 0 开始每次取L[0]、L[1]、L[2]……我们的循环里又在 pop 删除元素列表一直在变短索引就对不上了我们把实际过程走一遍开始L [Bart, Lisa, Adam] 第 1 次迭代for 取 L[0] → L[0] Bart → pop(0) 删除后L 变成 [Lisa, Adam] → 打印 Hello, Bart! → 打印 END 第 2 次迭代for 取 L[1] ← 注意索引到 1 了 → 现在的 L[1] AdamLisa 是 0 号了 → pop(0) 删除后L 变成 [Adam] → 打印 Hello, Lisa! → 打印 END 第 3 次迭代for 想取 L[2] → 但现在 L 只有 1 个元素没有 L[2] 了 → 循环结束Adam 被跳过了所以 Adam 不是没输出而是被 for 的索引跳过了它还在列表里躺着我们才不得不用print(fHello, Adam!)手动补。如果一定要写成 for in那么就只能这样写L[Bart,Lisa,Adam]## for i in L:# if len(L)0:# x L.pop(0) # 取出最前面的元素同时删除它# print(fHello, {x}!)# else:# break# print(END)# print(fHello, Adam!)# 如果非要 for可以复制一个副本foriinL[:]:# L[:] 是 L 的副本改 L 不影响迭代xL.pop(0)print(fHello,{x}!)先用切片复制一遍原列表切片公式text[起点:终点]。L[:]就是起点和终点都省略的切片意思是从头取到尾而切片操作天生就会生成一个全新的列表例如L[Bart,Lisa,Adam]copyL[:]# 从头取到尾得到一个新列表print(copy)# [Bart, Lisa, Adam] 内容一样print(copyL)# True 内容相等print(copyisL)# False 但不是同一个对象关键在最后一行copy is L是 False比较的是内容是否一样 → 一样Trueis比较的是是不是同一个东西 → 不是False可以使用 id() 查看身份证例如print(id(L))# 比如 123456print(id(L[:]))# 比如 654321 ← 不一样这里会输出2351607845248 2351607847104身份证不一样说明他们不是同一个东西每个运行环境 id 方法出来的不一样。而我们现在foriinL[:]:# for 遍历的是复制出来的那份L.pop(0)# pop 删的是原来的那份两边互不干扰for 按照原来的完整列表[Bart,Lisa,Adam]走 3 轮原列表被 pop 空Adam 不再被跳过。八、for 还是 while一句话判断法是不是很多同学有点绕分不清什么时候用 for什么时候用 while很简单这个问题是学循环的灵魂问题我教你一个一句话判断法知道要遍历几个 → 用 for不知道几个、只知道啥时候停 → 用 while再配上两个生活类比for 按清单办事清单上有 5 件事从头做到尾做完就结束。while 直到满意为止不知道要做几次但只要没满意就继续做。具体场景看例子用 for 的场景知道要遍历多少个# 遍历列表3 个名字遍历 3 次清清楚楚fornamein[Bart,Lisa,Adam]:print(name)# 固定次数打印 5 次foriinrange(5):print(第,i,次)# 遍历字符串逐个字符forcinPython:print(c)这些的共同点对象里有几个元素/几次一开始就定死了for 自己会数。用 while 的场景不知道几次只看条件# 直到用户输入 quit 才停不知道用户会输几次wordwhileword!quit:wordinput(输入点什么quit 退出)# 直到列表清空前面你的例子whileL:L.pop(0)# 直到数字减到 0前面 break 那个例子的 while 版n100whilen0:nn-2这些的共同点循环几次完全取决于运行中的变化只能靠条件判断该不该继续。对比着看场景用 for用 while遍历列表/元组/字符串✅ 首选可以但啰嗦固定次数如 100 次✅for i in range(100)要自己写计数器直到某个条件满足❌ 不行✅ 首选需要边删边遍历⚠️ 容易踩坑✅ 推荐处理用户输入直到退出❌ 不行✅ 首选还有一个捷径记忆法看到遍历、每个、依次、所有 → for看到直到、只要、当……时、不停直到 → while可以拿之前的代码对照一下foriinL:# 遍历所有名字 → for ✅whileL:# 直到列表清空 → while ✅whilen0:# 直到 n 不大于 0 → while ✅这样是不是清晰多啦以后写代码前先问自己一句我知道要循环几次吗答案会告诉你该用哪个九、continue接着是 continue和 break 不一样break 是提前结束continue 是提前进入循环例如L[Bart,Lisa,Adam]# for i in L:# print(fHello, {i}!)whileL![]:# while L: L非空就继续空了就停xL.pop(0)# 取出最前面的元素同时删除它ifxBart:continueprint(fHello,{x}!)print(空列表,L)print([]None)# False不等于会输出Hello, Lisa! Hello, Adam! 空列表 [] False直接跳过第一个元素循环就是这样。
返回列表