后端编程Python3-控制结构(python中控制结构)
off999 2024-10-19 07:14 26 浏览 0 评论
本节是第五讲的第九小节,上节为大家介绍了Python语言组合数据类型的迭代与复制,本节将为大家介绍Python语言的控制结构。
控制结构(Control Structures)
Python通过if语句实现了条件分支,通过while语句与for...in语句实现了循环。Python中还有一种条件表达式是一种if语句,也是Python对C风格语言中使用的三元算子(?:)相对应的内容。
条件分支(Conditional Branching)
下面给出的是Python条件分支语句的最通常的语法:
if boolean_expression1:
suite1
elif boolean_expression2:
suite2
elif boolean_expressionN:
suiteN
else:
else_suite
可以有0个或多个elif语句,最后一个elif语句是可选的。如果我们需要考虑某个特定情况,但在该情况出现时又不需要做什么,那么可以使用pass (充当“什么也不做"占位符)作为该分支的suite。
有些情况下,可以将一条if...else语句缩减为单一的条件表达式,条件表达式的语法是:
expression1 if boolean_expression else expression2 #如果boolean_expression为True,条件表达式的结果为expression1,否则为expression2。
通常的程序设计模式是将某变量设置为默认值,在必要的时候再改变该值,比如, 由于用户的请求进行改变,或者针对程序当前运行平台进行改变。下面给出的是使用 if语句的常规模式:
offset = 20
if not sys.platform.startswith("win"):
offset = 10
sys.platform变量存放的是当前平台的名称,比如,“Win32”或“linux2”。使用条件表达式,可以通过一行代码完成上面的功能:
offset = 20 if sys.platform.startswith("win") else 10
这里并不需要使用圆括号,但是使用圆括号可以避免微妙的陷阱,比如,假定我们想将width变量设置为100,并在margin为True时额外加10,我们可能会使用如下的代码:
width = 100 + 10 if margin else 0 # WRONG!
特别讨厌的地方在于,如果margin为True,上面的代码可以正确工作,并将width 设置为110;如果margin为False,就会错误地将width设置为0,而非100,这是因为,Python将100 + 10看做条件表达式的expression1部分,解决这一问题的方法是使用圆括号:
width = 100 + (10 if margin else 0)
圆括号还可以使得代码更清晰,更适合阅读。
条件分支可用于提高为用户打印的消息,比如,在报告处理的文件数量时,不再打印“0 file(s)”、“1 file(s)”,而是使用一对条件表达式:
print("{0} file{1}".format((count if count != 0 else "no"),("s” if count != 1 else "")))
上面的语句将打印“no files”、“1 file”、“2 files",并且同时会留下一个更专业的印象。
循环(Looping)
Python提供了 while循环与for ... in循环,这两种循环方式实际上都具有比第1章中所展示的基本语法更复杂的语法格式。
while 循环(while Loops)
下面给出的是while循环完整的、通常的语法格式:
while boolean_expression:
while_suite
else:
else_suite
else分支是可选的。只要boolean_expression为True, while块的suite就会执行。 如果boolean_expression为False或变为False,循环就会终止,此时,如果存在可选的else分支,就会执行其suite。在while块的suite内部,如果执行了continue语句, 就会跳转到循环起始处,并对boolean_expression的取值进行重新评估。如果循环不能正常终止,就会跳过所有可选的else分支。
可选的else分支这种叫法很容易让人困惑,因为只要循环是正常终止的,else分支的suite就总会执行。如果由于break语句、或由于返回语句(如果循环在函数或方法内)、或由于发生异常导致跳出循环,else分支的suite就不会执行。(发生异常时, Python会跳过else分支并寻找适当的异常处理部分。)另一方面,else分支的这些特点对while循环、for ...in循环以及try ... except块都是一样的。
让我们看一下else分支的实际使用。str.index()与list.index()方法可以返回给定字符串或数据项的索引位置,并在找不到时产生ValueError异常。str.find()方法完成同样的功能,但在找不到时不会产生异常,而是返回索引值-1,对于列表,没有等价的方法,但如果需要一个完成这一功能的函数,可以使用while循环创建:
def list_find(lst, target):
index = 0
while index < len(lst):
if lst[index] == target:
break
index += 1
else:
index = -1
return index
这一函数在给定的列表中搜索目标。如果找到了目标,就使用break语句终止循环,并返回适当的索引位置。如果找不到目标,就会循环完毕并正常终止,之后执行else的suite:将索引位置设置为-1,并返回该值。
for循环(for Loops)
与while循环类似,for... in循环的完整语法也包括else分支:
for expression in iterable:
for_suite
else:
else_suite
通常,expression或者是一个单独的变量,或者是一个变量序列,一般是以元组形式给出的。如果将元组或列表用于expression,则其中的每一数据项都会拆分到表达式的项。
如果在for... in循环suite中执行了continue语句,那么控制流立即跳转到循环起始处,并开始下一次迭代。如果循环正常执行完毕,就会终止循环,之后执行else suite。如果循环被跳出(由于执行了break语句或return语句),控制流会立即跳转到循环后的语句——所有可选的else suite将被跳过。同样地,如果发生异常,Python会跳过else 分支并寻找适当的异常处理程序。
下面给出了list_find()的for ... in循环实现版本,与while循环实现的版本类似, 这一版本也展示了 else分支的实际应用:
def list_find(lst, target):
for index, x in enumerate(lst):
if x == target:
break
else:
index = -1
return index
如上面代码段所示,在for ... in循环的表达式中创建的变量在循环终止后仍然存在。与所有局部变量类似,他们也将在其闭合范围结尾处终止存在。
异常处理(Exception Handling)
Python通过产生异常来指明发生错误或异常条件——尽管有些第三方Python库使用更过时的技术,比如“error”返回值。
捕获与产生异常(Catching and Raising Exceptions)
异常的捕获是使用try ...except 块实现的,其通常语法如下:
try:
try_suite
except exception_group1 as variable1:
except_suite1
......
except exception_groupN as variableN:
except_suiteN
else:
else_suite
finally:
finally_suite
其中至少要包含一个except块,但else与finally块都是可选的。在try块的suite 正常执行完毕时,会执行else块的suite—如果发生异常,就不会执行。如果存在一 个finally块,则最后总会执行。
每个except分支的异常组可以是一个单独的异常,也可以是包含在括号中的异常元组。对每个异常组,as variable部分是可选的。如果使用,该变量就会包含发生的异常,并可以在异常块的suite中进行存取。
如果某个异常发生在try块的suite中,那么每个except分支会顺序尝试执行。如果该异常与某个异常组匹配,则相应的suite得以执行。要与异常组进行匹配,异常必须与组中列出的异常类型(或其中的某一个)一致,或者与组中列出的异常类型(或其中的某一个)的子类一致。
比如,如果在字典查询中产生KeyError异常,那么包含Exception类的第一个 except分支将匹配这一异常,因为KeyError是Exception的(非直接的)子类。如果没有哪个组列出了 Exception (通常是这种情况),但是存在一个LookupError,那么 KeyError异常也可以匹配,因为KeyError是LookupError的子类。如果没有哪个组列 出了 Exception或LookupError,但是某个组列出了 KeyError,就将匹配该组。
下图展示了从异常体系中抽取的部分关系图:
#下面给出的是不正确使用的一个实例:
try:
x = d[5]
except LookupError: # WRONG ORDER
print("Lookup error occurred")
except KeyError:
print("lnvalid key used")
如果字典d不包含key为5的数据项,那么我们希望产生最具针对性的异常 KeyError,而不是最通常的异常LookupError,但是这里,KeyError except块代码总是无法执行到。如果产生KeyError异常,就会与LookupError except块匹配,因为 LookupError是KeyError的一个基类,也就是说,在异常体系中,LookupError要高于 KeyError,因此,在使用多个except块时,我们必须坚持对其排序,从最具针对性的 (在异常体系中最底层)异常到最通常(异常体系中最顶层)的异常。
try:
x = d[k / n]
except Exception: # BAD PRACTICE
print("Something happened")
要注意的是,上面这种使用except Exception的方法通常并不是一种好做法,因为这种做法将捕捉所有异常,从而很容易掩盖代码中的逻辑错误。在上面的实例中,程序的本意是捕捉KeyErrors,但是如果n为0,就会无意间并且寂静地捕获一个 ZeroDivisionError 异常。
直接写成except:也是可能的,也就是说,不设置异常组。写成这种风格的异常块将捕获任意异常,包括那些继承自BaseException而非Exception的异常,这种做法会导致与使用except Exception同样的问题,甚至更严重,通常情况下应该总是避免这种做法。
如果没有哪个except块匹配该异常,Python会沿着调用栈回溯,并寻找适当的异常处理程序。如果找不到合适的异常处理程序,程序将终止,并在控制台上打印该异常以及回溯信息。
如果没有异常产生,那么任意可选的else块都将执行。在所有情况下——也就是说,如果没有发生异常,或发生异常并被处理,或发生异常并回溯到调用栈——任意 finally块的suite总是会得以执行。如果没有异常产生,或产生的异常被某个except 块处理,那么finally块的suite将在最后执行;如果异常产生,但是没有匹配的except 块,就首先执行finally块的suite,之后将该异常在调用栈中回溯。在需要确保资源被正确释放时,这种执行机制是很有用的。下图勾勒了通常的try ... except... finally语句块控制流。
#下面给出list_find()函数的最终版本,使用了异常处理:
def list_find(lst, target):
try:
index = Ist.index(target)
except ValueError:
index = -1
return index
上面的代码中,有效地使用了 try... except块,将异常转换为错误值。也可以使用同样的方法捕捉某种异常并产生另一种异常——稍后将讨论这一技术。
Python还提供了更简单的try ... finally块,有时也是有用的:
try:
try_suite
finally:
finally_suite
不管try块的suite中发生什么(当然,计算机或程序崩溃除外),finally块的suite 都将得以执行。将with语句与上下文管理器一起使用,也可以达到try ... finally块的效果。
try ... except... finally块的一种常见应用是处理文件错误。比如,noblanks.py程序 从命令行读取一个文件名列表,对其中每个文件,生成一个同名文件,但是后缀名改为.nb,内容上则去除原有文件中的空白行。下面给出的是该程序的read_data()函数:
def read_data(filename):
lines =[]
fh = None
try:
fh = open(filename, encoding="utf8")
for line in fh:
if line.strip():
lines.append(line)
except (lOError, OSError) as err:
print(err)
return []
finally:
if fh is not None:
fh.close()
return lines
上面的代码中,我们将文件对象fh设置为None,因为open。调用可能失败,这种情况下不会为fh赋值(因而fh保持为None),并产生一个异常。如果产生我们指定的某个异常(lOError或OSError),在打印错误消息后,就会返回一个空列表。需要注意的是,在返回之前,finally块的suite将得以执行,因此文件将安全地关闭—— 如果此前该文件被成功打开。
还要注意的是,如果发生编码错误,即便我们并不捕捉相关的异常(ValueError), 文件仍然会安全地关闭。这种情况下,finally块的suite将得以执行,之后异常被向上传递到调用栈——此时没有返回值,因为函数是由于未处理的异常导致结束的。此外, 由于没有适当的except块捕捉编码错误异常,因此程序将终止并打印回溯信息。
我们可以将except分支写的稍详细一些:
except EnvironmentError as err:
print(err)
return []
上面的代码可以正常工作,因为EnvironmentError是lOError与OSError的基类。 在后面,我们将展示一个稍紧凑一些的惯用法,以确保文件被安全关闭,而不需要finally块。
产生异常(Raising Exceptions)
异常提供了一种改变控制流的有用方法。我们可以使用内置的异常,或创建自己的异常,以便产生我们所需要的异常并对其进行处理。有两种可以产生异常的语法:
raise exception(args)
raise exception(args) from original_exception
raise
使用第一种语法时,指定的异常应该或者是内置的异常,或者继承自Exception 的自定义异常。如果给定一些文本作为该异常的参数,那么在捕捉到该异常并打印时, 这些文本应该为输出信息。使用第二种语法,也就是没有指定异常时,raise将重新产生当前活跃的异常——如果当前没有,就会产生一个TypeError。
自定义异常(Custom Exceptions)
自定义异常是自定义的数据类型(类)。创建类在后面讲述,不过创建简单的自定义异常类型比较简单,这里我们展示其基本的语法:
class exceptionName(baseException): pass #基类应该为Exception类或继承自Exception的类。
found = False
for row, record in enumerate(table):
for column, field in enumerate(record):
for index, item in enumerate(field):
if item == target:
found = True
break
if found:
break
if found:
break
if found:
print("found at ({0}, {1}, {2})".format(row, column, index))
else:
print("not found")
上面这15行代码是复杂的,因为我们必须分别跳出每个循环。一种替代的解决方法是使用自定义异常:
class FoundException(Exception): pass
try:
for row, record in enumerate(table):
for column, field in enumerate(record):
for index, item in enumerate(field):
if item == target:
raise FoundException()
except FoundException:
print("found at ({0}, {1}, {2})".format(row, column, index))
else:
print("not found")
这种方法可以将代码削减到10行,或者11行(包含异常定义本身),并且更易于理解。如果发现了要寻找的数据项,就产生自定义的异常,并执行except块的suite, else块则被跳过。如果没有找到相应的数据项,就不会产生异常,并在最后执行else suite。
以上内容部分摘自视频课程05后端编程Python-9控制结构,更多实操示例请参照视频讲解。跟着张员外讲编程,学习更轻松,不花钱还能学习真本领。
相关推荐
- pubg加速器免费版(pubg加速器免费版无广告)
-
现在加速吃鸡的游戏加速器是有专线路线的比较好,专线的稳定很多,不过目前是没有完全免费的加速软件,很多都可以先体验,注册就可以体验的,可以多去体验几款,对比一下。目前的加速器可以分为三个等级第一等级:全...
-
- 如何用u盘重装电脑系统win7(用u盘怎样重装系统win7)
-
u盘怎么装win7系统步骤如下:1、先下载Windows7镜像,根据自己需求选择下载的版本:简化版、家庭基础版、家庭高级版、企业版等。2、下载工具软碟通。直接在搜索引擎中输入“软碟通”,选择合适的下载地址,直接下载安装即可。3、制作系统U...
-
2025-12-27 08:51 off999
- 系统驱动怎么安装(系统驱动的安装)
-
首先进入系统的设备管理器,检查一下是否存在有没有正确安装或者找不到的驱动程序的设备,然后进入硬件生产厂商官网去下载对应的操作系统的驱动程序,进行安装。如果嫌麻烦,可下载第三方软件进行辅助安装。1、如果...
-
- 设置bios密码(银河麒麟怎么设置bios密码)
-
想电脑BIOS开机密码,其实很简单,只要进入BIOS设置界面,然后选择“security”选项卡,在“security”内设置好开机密码即可。下面就跟随小编一起来学习一下具体提设置步骤吧!1、首先开机,然后快速按“F2”或者“F12”进入B...
-
2025-12-27 07:51 off999
- 华硕售后服务中心查询(华硕售后维修服务网点查询)
-
首先查看包装盒、保修卡、机器底部。三个地方的SN码及机器的序列号是不是一致。如果不一致那一定是有问题的。2然后,如果一致,我们可以拨打华硕的客服,通过机器的序列号,查询机器的基本情况,然后与说明书上的...
- 如何更改硬盘分区(硬盘怎么更改分区)
-
要修改磁盘分区,首先需要使用磁盘管理工具,如DiskManagement(Windows)或DiskUtility(Mac)。在工具中,选择要修改的磁盘并右键点击,然后选择“修改分区”选项。接着,...
- 无线路由器当交换机使用(路由器当交换机用无线wifi还可以上网吗)
-
若您想将无线路由器用作交换机,您可以按照以下步骤操作:1.确保您的无线路由器具有交换器功能。不是所有的无线路由器都具备此功能,请先确保您的设备支持。2.将您的无线路由器与网络中的其他设备连接。通常...
- computer(computer lab)
-
"电脑"这个名称实际上是人们对具有计算功能电子设备的俗称。而计算机(Computer)则是这个设备的正式名称,因为"计算"是其核心功能。在英文中,Computer是指可...
- 电脑重置20多个小时了(重置电脑一直12%)
-
重置电脑时间太长了解决办法如下1、将电脑关机然后开机或者直接点击重启,然后按住DELETE键,电脑会自动进入到BIOS;2、电脑屏幕上会显示两个选项,两个选项一般都在电脑屏幕的右方;3、其中一个选项是...
- 电脑虚拟机是什么(电脑虚拟机有啥用)
-
电脑虚拟机(VirtualMachine,VM),也称为虚拟计算机,是一种软件模拟的计算机,它在现有的计算机硬件上创建一个虚拟的计算机环境。这个虚拟环境可以用来运行操作系统、应用程序等软件,就像是在...
- 键盘图片大图(键盘图片大图清晰)
-
这个是仿苹果机上的无线键盘(妙控一代)的,属于山寨产品。1、在手机的微信或者短信或者其他可以打开键盘的应用中打开键盘,点击键盘左上角的输入法设置图标,页面显示输入法的各种设置功能;2、在输入法的设置...
- win11系统可以更新吗(w11系统可以用了吗)
-
可以1.点击“开始”,打开“设置”。2.找到“更新和安全”,选择“预览体验计划”。3.点击“开始”,需要登录微软账户。4.登录完成后弹出一个升级的渠道,选择dev进行下载win11即可。方法二:首...
- winxp安装系统镜像iso下载(xp的镜像系统怎么安装)
-
要安装一个ISO镜像文件,首先需要将ISO文件挂载到计算机上。在Windows系统中,可以右键点击ISO文件,并选择“挂载”选项,然后打开文件资源管理器就能看到ISO文件被挂载的虚拟驱动器。在Linu...
欢迎 你 发表评论:
- 一周热门
-
-
抖音上好看的小姐姐,Python给你都下载了
-
全网最简单易懂!495页Python漫画教程,高清PDF版免费下载
-
Python 3.14 的 UUIDv6/v7/v8 上新,别再用 uuid4 () 啦!
-
飞牛NAS部署TVGate Docker项目,实现内网一键转发、代理、jx
-
python入门到脱坑 输入与输出—str()函数
-
宝塔面板如何添加免费waf防火墙?(宝塔面板开启https)
-
Python三目运算基础与进阶_python三目运算符判断三个变量
-
(新版)Python 分布式爬虫与 JS 逆向进阶实战吾爱分享
-
失业程序员复习python笔记——条件与循环
-
系统u盘安装(win11系统u盘安装)
-
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python进度条 (67)
- python吧 (67)
- python的for循环 (65)
- python格式化字符串 (61)
- python静态方法 (57)
- python列表切片 (59)
- python面向对象编程 (60)
- python 代码加密 (65)
- python串口编程 (77)
- python封装 (57)
- python写入txt (66)
- python读取文件夹下所有文件 (59)
- python操作mysql数据库 (66)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python多态 (60)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)
