Python 之进阶语法:with...as...

news/2024/10/8 6:54:02/
1. Python with…as…是什么

Python 的 with…as… 语句,就像一个贴心的管家,负责照顾你的资源,让你不再担心忘记关闭文件、网络连接或数据库事务等。这个管家在你进入“房间”时自动打开门,离开时帮你把门关上,真的是非常贴心!

这个管家的工作方式很简单,你只需要在 with 后面跟上你要管理的资源,然后在 as 后面给这个资源起个名字。一旦你进入了这个“房间”,这个资源就被自动管理了。

1.1 with…as…语法结构
python">with expression [as target]:with body

参数说明:

expression:是一个需要执行的表达式;
target:是一个变量或者元组,存储的是expression表达式执行返回的结果,[ ]表示该参数为可选参数。

1.2 with…as…用法示例

例如,当你打开一个文件时,你可能会这样写:

python">file = open("example.txt", "r")  # 手动打开
content = file.read()  
file.close()  # 手动关闭

但是这样写有个问题,如果代码在读取文件内容或关闭文件时出现异常,文件可能不会被正确关闭。这时,你就可以请出 with…as… 语句来帮忙:

python">with open("example.txt", "r") as file:  content = file.read()  # 在这里你可以放心地使用file,不必担心忘记关闭它。

 这样,无论在 with 块中的代码是否出现异常,文件都会在退出块时被自动关闭,你就不必再担心忘记关闭文件了。

with…as…语句,在Python中叫做:上下文管理器,它在 Python 中实现了自动分配并释放资源。

2. Python with…as…工作原理
2.1 with…as…的由来

with…as 是 python 的控制流语句,像 if ,while一样。

with…as 语句是简化版的 try…except…finally语句。

先理解一下 try…except…finally 语句是干啥的。

实际上 try…except 语句和 try…finally 语句是两种语句,用于不同的场景。但是当二者结合在一起时,可以“实现稳定性和灵活性更好的设计”。

2.1.1 try…except 语句

用于处理程序执行过程中的异常情况,比如语法错误、从未定义变量上取值等等,也就是一些python程序本身引发的异常、报错。比如你在python下面输入 1 / 0:

python">a = 1 / 0
print(a)
# ZeroDivisionError: division by zero

是的,上面的代码会引发一个ZeroDivisionError异常,因为它在尝试将1除以0。在Python中,任何数字除以0都是未定义的,所以会引发这个错误。

如果你想避免这个错误,你可以使用tryexcept语句来捕获这个异常:

python"># 声明变量a,并赋值为1除以0,这会导致ZeroDivisionError  
a = 1 / 0  # 尝试执行接下来的代码块,如果发生异常,则执行except块  
try:  # 打印变量a的值,因为a = 1 / 0,所以这里会引发ZeroDivisionError  print(a)  # 如果try块中的代码引发ZeroDivisionError异常,则执行此except块  
except ZeroDivisionError:    # 当除以零时,打印一个错误消息  print("Division by zero is not allowed!")

这样,当尝试除以零时,程序不会崩溃,而是会输出一个错误消息。

try…except 的标准格式

python">try:# normal block
except A:# exc A block
except:# exc other block
else:# noError block 

程序执行流程是:

–>执行normal block

–>发现有A错误,执行 exc A block(即处理异常)

–>结束

如果没有A错误呢?

–>执行normal block

–>发现B错误,开始寻找匹配B的异常处理方法,发现A,跳过,发现except others(即except:),执行exc other block

–>结束

如果没有错误呢?

–>执行normal block

–>全程没有错误,跳入else 执行noError block

–>结束

我们发现,一旦跳入了某条except语句,就会执行相应的异常处理方法(block),执行完毕就会结束。不会再返回try的normal block继续执行了。

python">try:a = 1 / 2  # a normal number/variableprint(a)b = 1 / 0  # an abnormal number/variableprint(b)c = 2 / 1  # a normal number/variableprint(c)
except:print("Error")

结果是,先打出了一个0.5,又打出了一个Error。就是把ZeroDivisionError错误捕获了。

先执行 try 后面这一堆语句,由上至下:

  • step1: a 正常,打印a. 于是打印出0.5 (python3.x以后都输出浮点数)
  • step2: b, 不正常了,0 不能做除数,所以这是一个错误。直接跳到except报错去。于是打印了Error。
  • step3: 其实没有step3,因为程序结束了。c是在错误发生之后的b语句后才出现,根本轮不到执行它。也就看不到打印出的c了

但这还不是 try…except 的所有用法,except后面还能跟表达式的。

所谓的表达式,就是错误的定义。也就是说,我们可以捕捉一些我们想要捕捉的异常。而不是什么异常都报出来。

异常分为两类:

  • 自定义异常

我们先抛开自定义异常(因为涉及到类的概念),看看 except 都能捕捉到哪些 python 标准异常。

请查看:Python 异常处理

2.1.2 try…finallly 语句

用于无论执行过程中有没有异常,都要执行清场工作。

python">try:  execution block  # 正常执行模块  
except A:  exc A block # 发生A错误时执行  
except B:  exc B block # 发生B错误时执行  
except:  other block # 发生除了A,B错误以外的其他错误时执行  
else:  if no exception, jump to here # 没有错误时执行  
finally:  final block  # 总是执行  

tips: 注意顺序不能乱,否则会有语法错误。如果用 else 就必须有 except,否则会有语法错误。

python">try:a = 1 / 2print(a)print(m)  # 抛出 NameError异常, 此后的语句都不在执行b = 1 / 0print(b)c = 2 / 1print(c)
except NameError:print("Ops!!")  # 捕获到异常
except ZeroDivisionError:print("Wrong math!!")
except:print("Error")
else:print("No error! yeah!")
finally:  # 是否异常都执行该代码块print("Successfully!")

代码分析:

  1. try 块开始。
  2. a = 1 / 2:这行代码是合法的,所以 a 被赋值为 0.5
  3. print(a):输出 0.5
  4. print(m):这行代码尝试打印变量 m,但在此之前没有定义 m,所以会抛出一个 NameError 异常。
  5. 由于在 try 块中抛出了 NameError 异常,所以会跳到相应的 except 块。该块捕获到异常并输出 “Ops!!”。
  6. 由于异常已经被捕获,后面的代码(包括 b = 1 / 0print(b)c = 2 / 1 和 print(c))都不会执行。
  7. 跳过 else 块(因为有一个被捕获的异常)。
  8. 进入 finally 块,并输出 “Successfully!”。

总结:

  • 当运行此代码时,输出将是:
python">0.5 
Ops!! 
Successfully!
  • 注意:尽管有 b = 1 / 0 和 c = 2 / 1,但它们不会被执行或输出,因为前面的 NameError 异常已被捕获。

说完上面两个概念,我们再来说说 with…as…语句。with…as…是从Python2.5引入的一个新的语法,它是一种上下文管理协议,目的在于从流程图中把 try,except 和finally 关键字和资源分配释放相关代码统统去掉,简化try...except...finlally的处理流程。

2.2 with…as…工作原理

with…as…语句相当于下面这段代码:

python">try:  # 尝试打开名为'example.txt'的文件,模式为'r',表示只读模式。  f = open('example.txt','r')  
except:  # 如果在尝试打开文件时发生任何异常(例如文件不存在),则执行此块。  print('fail to open')  # 打印错误消息,告知用户无法打开文件。  exit()  # 终止程序。  
else:  # 如果打开文件成功,则尝试读取文件内容并打印  print(f.read())finally:  # 不论是否发生异常,最后都会执行此块。  f.close()  # 关闭文件。这一步很重要,因为它确保文件资源被正确释放。

这是不是很麻烦,但正确的方法就是这么写。
我们为什么要写finally,是因为防止程序抛出异常最后不能关闭文件,但是需要关闭文件有一个前提就是文件已经打开了。


http://www.ppmy.cn/news/1536002.html

相关文章

C++【类和对象】(友元、内部类与匿名对象)

文章目录 1.友元2.内部类3.匿名对象结语 1.友元 友元提供了⼀种突破类访问限定符封装的方式,友元分为:友元函数和友元类,在函数声明或者类声明的前面加friend,并且把友元声明放到⼀个类的里面。外部友元函数可访问类的私有和保护…

python pass的作用

class Phone: IMEI None # 序列号 producer “ITCAST” # 厂商 def call_by_4g(self):print("4g通话")class Phone2022(Phone): face_id “10001” # 面部识别ID def call_by_5g(self):print("2022年新功能:5g通话")class NFCReader: nfc_ty…

Prompt技巧总结和示例分享

"Prompt"(提示)在人工智能中通常指的是输入给模型的文本,用于引导模型生成预期的输出。在使用人工智能助手时,有效的提示技巧可以帮助你获得更准确和有用的回答。 以下是一些单轮对话提示时的技巧: 明确具体…

【FPGA】面试八股

1.FPGA的底层资源有哪些 (1)可编程的逻辑资源 可编程的逻辑单元由查找表(LUT),数据选择器(MUX),进位链(Carry Chain)和触发器(Flip-Flop) (2&…

Python | 由高程计算坡度和坡向

写在前面 之前参加一个比赛,提供了中国的高程数据,可以基于该数据进一步计算坡度和坡向进行相关分析。 对于坡度和坡向,这里分享一个找到的库,可以方便快捷的计算。这个库为:RichDEM,官网地址如下 https…

SparkCore与FlinkCore的区别有哪些

1.架构理念方面: Spark Core: Spark 基于 RDD(弹性分布式数据集)的概念构建。RDD 是一个不可变的、分布式的对象集合,它可以在集群中的多个节点上进行并行计算。例如,在处理大规模的日志文件时,Spark 可以将日志文件…

前端组件化开发

假设这个页面是vue开发的,如果一整个页面都是编写在一个vue文件里面,后期不好维护,会特别的庞大,那么如何这个时候需要进行组件化开发。组件化开发后必然会带来一个问题需要进行组件之间的通信。组要是父子组件之间通信&#xff0…

基于SpringBoot博物馆游客预约系统【附源码】

基于SpringBoot博物馆游客预约系统 效果如下: 主页面 注册界面 展品信息界面 论坛交流界面 后台登陆界面 后台主界面 参观预约界面 留言板界面 研究背景 随着现代社会的快速发展和人们生活水平的提高,文化生活需求也在日益增加。博物馆作为传承文化、…