python with语句 局部变量_Python 的 with 语句详解

class opened(object):

def __init__(self, name):

self.handle = open(name)

def __enter__(self):

return self.handle

def __exit__(self, type, value, trackback):

self.handle.close()

with opened('/tmp/a.txt') as f:

for line in f.readlines():

print(line)

注意我们定了一个名字叫opened的辅助类,并实现了__enter__和__exit__方法,__enter__方法没有参数,__exit__方法的3个参数,分别代表异常的类型、值、以及堆栈信息,如果没有异常,3个入参的值都为None。

如果你不喜欢定义class,还可以用Python标准库提供的contextlib来实现:

复制代码 代码如下:

from contextlib import contextmanager

@contextmanager

def opened(name):

f = open(name)

try:

yield f

finally:

f.close()

with opened('/tmp/a.txt') as f:

for line in f.readlines():

print(line)

使用contextmanager的函数,yield只能返回一个参数,而yield后面是处理清理工作的代码。在我们读取文件的例子中,就是关闭文件句柄。这里原理上和我们之前实现的类opened是相同的,有兴趣的可以参考一下contextmanager的源代码。

三、应用场景废话了这么多,那么到底那些场景下该使用with,有没有一些优秀的例子?当然啦,不然这篇文章意义何在。以下摘自PEP 343。

一个确保代码执行前加锁,执行后释放锁的模板:

复制代码 代码如下:

@contextmanager

def locked(lock):

lock.acquire()

try:

yield

finally:

lock.release()

with locked(myLock):

# Code here executes with myLock held. The lock is

# guaranteed to be released when the block is left (even

# if via return or by an uncaught exception).

数据库事务的提交和回滚:

复制代码 代码如下:

@contextmanager

def transaction(db):

db.begin()

try:

yield None

except:

db.rollback()

raise

else:

db.commit()

重定向stdout:

复制代码 代码如下:

@contextmanager

def stdout_redirected(new_stdout):

save_stdout = sys.stdout

sys.stdout = new_stdout

try:

yield None

finally:

sys.stdout = save_stdout

with opened(filename, "w") as f:

with stdout_redirected(f):

print "Hello world"

注意上面的例子不是线程安全的,再多线程环境中要小心使用。

四、总结

with是对try…expect…finally语法的一种简化,并且提供了对于异常非常好的处理方式。在Python有2种方式来实现with语法:class-based和decorator-based,2种方式在原理上是等价的,可以根据具体场景自己选择。

with最初起源于一种block…as…的语法,但是这种语法被很多人所唾弃,最后诞生了with,关于这段历史依然可以去参考PEP-343和PEP-340

本文原创发布php中文网,转载请注明出处,感谢您的尊重!

相关文章

相关视频

网友评论

文明上网理性发言,请遵守 新闻评论服务协议我要评论

立即提交

专题推荐独孤九贱-php全栈开发教程

全栈 100W+

主讲:Peter-Zhu 轻松幽默、简短易学,非常适合PHP学习入门

玉女心经-web前端开发教程

入门 50W+

主讲:灭绝师太 由浅入深、明快简洁,非常适合前端学习入门

天龙八部-实战开发教程

实战 80W+

主讲:西门大官人 思路清晰、严谨规范,适合有一定web编程基础学习

php中文网:公益在线php培训,帮助PHP学习者快速成长!

Copyright 2014-2020 https://www.php.cn/ All Rights Reserved | 苏ICP备2020058653号-1

  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值