周日茶话会开始更新啦!
亲爱的小伙伴们,大家好,我们的周末茶话会开始更新啦!
茶话会目前主要分为两个模块
- 编程小白大战Python
- 小苏的Python进阶之路
周日茶话会的创作目的
我们的“茶话会”是每周日在实验室进行的,一开始的目的是大家通过每周固定的一个时间,一起交流自己的编程学习心得,从而达到相互督促,共同进步的目的。后来在实践中发现,每次交流的内容没有一个记录实在是很可惜,于是我决定每次讨论结束后,将大家讨论的内容记录下来,同时将每次讨论中遇到的问题在推文中描述清楚,记录大家的学习轨迹,便于大家的后续复习。
学习笔记有什么好看的呢?
既然将讨论的内容决定以一系列推文的形式写出来,就意味着我们的《周日茶话会》系列将不仅仅是单纯的笔记记录,而是对每次讨论涉及到的知识点进行整合、梳理、深化。
在“编程小白大战Python”中,我们将从最基础的Python概念出发,对每一个语法点,每一个语法糖做深入的剖析,而不是简单的介绍基础的语法概念。“入门”是起点,但远远不是我们推文的终点。在“小苏的Python进阶之路”中,我们将记录小苏后端学习的进程,一起搞清楚Web开发中遇到的每一个知识点。
所以无论你是刚刚学习Python编程的新手,还是有其他编程语言经验,相信这一系列的推文总是有你感兴趣的内容哒~
进入正题---Python中的上下文管理器
没有上下文管理器的场景
首先我们看看在没有上下文管理器的语言中,我们要打开一个资源要进行的工作,我们以打开一个文件为例。
file = open('a.txt', 'r')
....do something....
file.close()
我们对文件、数据库连接等进行操作时,一定要记得手动释放资源,防止出现问题。可是这样一来很繁琐,也容易忘记。在上面的例子中,还隐藏着一个小小的缺陷,如果在文件操作的过程中发生了异常,很可能导致后面的file.close()不会被执行,这样将导致资源不能被及时释放。当然,我们可以使用try-finally的语句来实现:
file = open('a.txt', 'r')
try:
....do something....
finally:
flie.close()
这样可以保障即使发生异常,也可以清理掉占用的资源。但是这样的写法问题在于,当我们对文件的操作(do something) 很多,而且程序中频繁出现对文件资源的访问时,程序就会变得很臃肿丑陋。为了解决这个问题,Python为我们提供了with的语法糖。
With上下文管理器
下面我们来看看用Python语法糖实现的效果
with open('a.txt', 'r') as f:
....do something....
借助Python提供给我们的语法糖,我们可以优雅的实现资源的管理,不用去手动回收资源。下面,我们对with语法糖做一个深入的介绍。
Python上下文管理器中的核心概念
上下文管理器: 实现了上下文协议的类被称为上下文管理器
上下文协议: 指明类要实现
__
enter()__
和__
exit()__
方法__enter()__: 本方法在with语句开始时被Python的解释器调用,可以(非必须)向with语句返回一个值
__exit()__: 本方法在with语句结束时被Python的解释器调用,可以在其中编写资源清理相关的操作
通过上面的几个概念,再结合上面的实例,我们来讲解一下我们用with语法打开文件时的过程:
首先,Python首先进入Open类中的init方法来对对象进行必要的初始化操作
然后,进入__enter()__方法中,完成所有的创建工作,并返回一个file的实例,在with语法中被我们命名为f。
最后,在对文件的操作结束后,进入__exit__()方法中进行文件的清理工作。
因为Python的封装隐藏了一些细节,我们可能对open()是不是一个类心存疑虑,这里我也没能通过调试进入到open()的内部中查看源码,所以我们接下来通过将自己定义的类实现上下文协议来验证我们的知识。
手动实现上下文管理器
class OurImplement:
def __init__(self):
print("Now we are in the __init__")
def __enter__(self):
print('Now we are in the enter')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('Now we are in exit')
def show(self):
print('do something')
with OurImplement() as f:
f.show()
在上面的代码中,我们在enter方法里将实例化的变量返回,并通过调用f.show()来进行验证。
结果如下:
Now we are in the __init__
Now we are in the enter
do something
Now we are in exit
从执行的结果我们可以看到,我们首先执行了我们自己定义类的构造函数,在构造函数结束后,就进入了with 语法糖中的__
enter__
()方法,f实际上是我们在enter函数中的返回值(这个值也可以返回数值等,不是必须返回对象,甚至可以选择不返回值,这里大家可以自行验证)。当我们对资源的操作结束后,就进入__
exit__
()函数完成资源清理的相关操作。
小结
本期是茶话会的第一期,主要对Python中的上下文管理器做了一些简单的讨论。可以看到,虽然都说Python语言很简单,但是其实简单的背后是通过层层的封装和优雅的设计隐藏了底层的复杂细节。在编写一般的业务逻辑代码时,可能大多数时候不需要了解这些语言的机制,但是一旦涉及到阅读源码或者是需要自己对框架进行订制,甚至是开发属于自己的框架时,这些知识就不可或缺了。本期只是对上下文管理器的一个简单浅析,下期将结合yield语法以及Python的装饰器,讲解Python contexlib中提供的 contexmanager装饰器。
今天的内容就到这里大家再见ヾ( ̄▽ ̄)ByeBye~
关于更新时间
目前计划的更新时间是每周一篇,但是考虑到期末复习呀,大创项目呀等一系列问题,拖更可能还是难以避免的吧...手动伤心T_T
题外话
其实这次已经是我第二次开始准备写作了,第一次是在CSDN上尝试写博客,写了一篇发现耗费了巨大的时间,没多久就放弃了。可是后来发现,持续的写作确实是提升自己最好的手段,一个知识点看过,学过,甚至上手实践过,都不一定能对其完完全全掌握,而如果能给别人明明白白的讲清楚,给别人讲懂,或者写一篇文章能让人看懂,在这个过程中花费的精力和心血都不会白费,会让自己以前没有关注到的点更加扎实,与其说是讲给别人听,不如说是在完善自己的知识体系。这次也一定要吸取上一次失败的教训,上一次的写作中,总担心这里的图画的不够美观,那里的排版不太合格,结果让输出无关的事情耗费了很多的时间,得不偿失。
The best is the enemy of the good.
这一次,用行动代替完美的筹划。
PS:你们的灵魂画师即将上线