python学习笔记之with语句

时间:2019-02-20
本文章向大家介绍python学习笔记之with语句,主要包括python学习笔记之with语句使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

一、with的应用场景:

在python语言中,with语句适用于资源相关操作,锁相关操作,文件相关操作,异常处理等相关操作情景,可以代替try...except...finally...的模式,让程序员不用写一些可能会忘写的收尾的代码,使代码更简洁。

如下代码:在编码中可能会忘记关闭文件,或者在读取文件时发生异常,没有进行任何处理

import os

if not os.path.exists(u'F:/test'):
    os.makedirs('F:/test')
f=open(u'F:/test/text.txt','r+')#打开文件,赋值给句柄
print f.read()#操作句柄读取数据
f.close()#关闭文件

 如下代码:对可能出现的异常进行处理,finally关闭文件

import os

if not os.path.exists(u'F:/test'):
    os.makedirs('F:/test')
try:    
    f=open(u'F:/test/text.txt','r+')#打开文件,赋值给句柄
    print f.read()#操作句柄读取数据
except:
    print 'fail to open'
    exit(-1)
finally:
    f.close()#关闭文件

为了代码简介,python用with来优雅的处理这段代码 

import os

if not os.path.exists(u'F:/test'):
    os.makedirs('F:/test')
  
with open(u'F:/test/text.txt','r+') as f:#打开文件,赋值给句柄
    print f.read()#操作句柄读取数据

二、with语句原理

with expression [as target]:

        with-body

expression是任意表达式,获取上下文管理器,as target可选,with-body是with语句的语句体 

  1. 计算expression,并获取上下文管理器
  2. 保存上下文管理器的__exit()__方法
  3. 调用上下文管理器__enter()__方法
  4. 如果有as target,__enter()__方法的返回值赋给target
  5. 执行with语句体的内容,eg:上面打印出利用文件对象读取的文件内容
  6. 不管是否出现异常,调用第二步保存的上下文管理器的__exit()__方法,这里如果with语句体执行机过程中发生异常导致程序退出,那么异常的type、value、traceback等作为参数传递给__exit()__方法,否则,传递三个None

1、采用装饰器定义上下文管理器:

#coding:utf-8
from contextlib import contextmanager

@contextmanager
def demo():
    print '__enter()__'
    yield 'contextmangager demo'
    print '__exit()__'
    
with demo() as demo:
    print 'with-body: '+demo
__enter()__
with-body: contextmangager demo
__exit()__

 2、采用自定义支持closing的对象:

#coding:utf-8
class closing(object):
    def __init__(self,thing):
        self.thing=thing
    def __enter__(self):
        print '__enter()__'
        return self.thing
    def __exit__(self,*exc_info):
        print '__exit()__'
        self.thing.close()
        
# 这里closing上下文管理器包装起来的对象必须具有close()方法的定义,否则会报错的
class demo():
    def __init__(self):
        self.thing=open('C:\Users\***\Desktop\111.txt','w')
    def run(self):
        print "function running"
    def close(self):
        self.thing.close()

with closing(demo()) as demo:
    demo.run()
__enter()__
function running
__exit()__

 3、采用类定义上下文管理器(廖雪峰大神教程的webapp里面就有许多这样的例子)

#coding:utf-8
k=0
m=0
class Sample:
    def __init__(self):
        global k
        k+=1
        print k
    def __enter__(self):
        global k
        k+=1
        print k
        print "__enter__()"
        global m
        m+=1
        return m
    def __exit__(self, type, value, trace):
        print "__exit__()"
        
with Sample() as sample:
    print sample
1
2
__enter__()
1
__exit__()

这里强调一点:看了许多博客,有的博客里面指出as target操作,是将expression赋值给target,这是不对的,从上面例子可以看出,是将__enter__()方法返回值赋值给target。