百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

后端编程Python3-控制结构(python中控制结构)

off999 2024-10-19 07:14 23 浏览 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控制结构,更多实操示例请参照视频讲解。跟着张员外讲编程,学习更轻松,不花钱还能学习真本领。

相关推荐

复制粘贴不了怎么解决(电脑不能复制粘贴了怎么处理)

1、查看手机输入法的剪贴板选项,是否有复制的文本,如果有就直接点击就可以直接输入了。2、复制后,长按不出来粘贴键的时候,需要把应用程序关闭掉重新开,重新复制粘贴,或者尝试重启手机。3、可以尝试重新复制...

u盘被写保护去除步骤(u盘的被写保护怎么解除)

U盘被写保护通常是因为存储器故障、病毒感染、文件系统损坏等原因导致的,但可以通过以下几种方法进行解除:1.检查U盘开关:一些U盘可能会有物理上的写保护开关,将其关闭即可解除写保护。2.使用命令行清...

电脑蓝屏怎么用u盘重装系统(电脑蓝屏重装系统教程u盘)

U盘装系统步骤:1.制作U盘启动盘。这里推荐U启动U盘启动盘制作工具,在网上一搜便是。2.U盘启动盘做好了,我们还需要一个GHOST文件,可以从网上下载一个ghost版的XP/WIN7/WIN8系统,...

erp管理软件(erp管理软件免费版)
erp管理软件(erp管理软件免费版)

用友的ERP应该说从3万-3000都有ERP的价格随着企业的规模不同,价格也是不一样的。因为企业规模不同产生的效果也是不一样的,所以用友的产品分T1/T3/T6/U8/U9/NC3万小企业做个财务业务一体化还是勉强可以做的。只...

2025-11-11 09:03 off999

笔记本启动黑屏怎么回事(笔记本启动黑屏没反应)

笔记本开机后黑屏最常遇到的一种情况:因随便点击垃圾网站而导致电脑中脑或受到木马的侵袭,致使电脑系统瘫痪,解决的办法就是重装电脑系统,装好系统后安装查毒软件,定期对电脑进行杀毒全盘扫描,然后平时尽量不要...

win7系统怎么开wifi热点(win7如何开wifi热点)

 1、首先确认你的无线网卡开启。在开始菜单中依次找到“所有程序”--“附件”--“命令提示符”,右键“以管理员身份运行”;   2、在“命令提示符”里输入“netshwlans...

无线路由桥接设置方法(无线路由器无线桥接设置)

1、首先在电脑上输入并登录第一台路由器的IP地址。2、进入路由器管理界面之后,点击“无线设置”,然后点击基本设置中设置“SSID号”,接着点击“信道”,然后设置固定信号道。3、返回无线设置菜单栏,选择...

win10企业版激活命令(win10企业版cmd激活命令)

关于这个问题,Windows10企业版可以通过以下方法进行激活:1.使用企业版密钥激活:如果你已经有了Windows10企业版的密钥,可以在“设置”中的“更新和安全”中选择“激活”来输入密钥进行...

如何恢复备份数据(备份的数据怎么恢复到手机上)
如何恢复备份数据(备份的数据怎么恢复到手机上)

把备份删了的话,一键还原目前是用不了的。现在唯一的办法,是从网上下载一个数据恢复类的软件,只要的备份还没有被别的软件覆盖,是应该可以数据恢复回来的。不能保证百分之百得成功,但是恢复几率还很大的,你可以试试,操作方法首先点击手机“设置”。然后...

2025-11-11 06:51 off999

笔记本无线网卡怎么使用(笔记本无线网卡怎么使用教程)

笔记本无线网卡设置;第一:你要确定你的本本是否有无线上网功能,如果没有就得加个无线网卡;第二:有的话就打开无线网络接受开关;第三:程序设置主要就是在网上邻居的属性里,打开无线上网打开“网上邻居”的“属...

鲁大师电脑版官方下载(鲁大师电脑版官方下载安装)

因为鲁大师是跑分软件,它会拖慢电脑的运行速度,还会占据大量的内存,如果你的电脑配置不是太好的话,装了鲁大师只会雪上加霜,非但得不到任何优化作用,还会拖慢电脑的启动速度,造成不必要的损耗。玩游戏都会卡顿...

win10怎么开机进入安全模式(win10开机怎么进安全模式怎么进)

进入Windows10安全模式有以下几种方法:方法一:使用开机高级选项1.在按下电源开机键后,持续按住F8键,直到你进入启动选项页面;2.从菜单中选择“安全模式”。方法二:使用系统配置1...

华硕电脑怎么重新安装系统(华硕电脑怎么重新安装系统教程)

第一步:备份重要数据重装系统前,务必先备份重要的个人数据。你可以将数据保存在外部存储设备上,或者使用云存储服务,确保数据安全可靠。第二步:下载系统镜像为了重装系统,你需要下载华硕笔记本电脑适用的操作系...

电脑显示此windows副本不是正版

1、第一步在电脑搜索框搜索命令提示符,鼠标右键以管理员的身份运行,2、第二步以管理员身份进去命令提示符之后输入"SLMGR-REARM",3、第三步按回车键可以看到命令已经成功重启一下...

电脑怎么复制粘贴按键(电脑复制粘贴按键是哪个)

电脑键盘上的粘贴键是:Ctrl+V按键。具体操作:1、以在excel表格中进行复制粘贴操作为例,首先选中需要复制粘贴操作的单元格。2、然后按下键盘上的“Ctrl+C”按键执行复制操作。3、然后将鼠标单...

取消回复欢迎 发表评论: