__exit__,__enter__函数with语句的组合应用
简介
设计对象类时,我们可以为对象类新增两个方法,一个是__enter(self)__,一个是__exit__(self, exc_type, exc_val, exc_tb)。
__enter(self)__
负责返回一个值,该返回值将赋值给as子句后面的var_name,通常返回对象自己,即“self”。函数优先于with后面的“代码块”(statements1,statements2,……)被执行。
__exit__(self, exc_type, exc_val, exc_tb)
执行完with后面的代码块后自动调用该函数。with语句后面的“代码块”中有异常(不包括因调用某函数,由被调用函数内部抛出的异常),会把异常类型,异常值,异常跟踪信息分别赋值给函数参数exc_type, exc_val, exc_tb,没有异常的情况下,exc_type, exc_val, exc_tb值都为None。另外,如果该函数返回True、1类值的Boolean真值,那么将忽略“代码块”中的异常,停止执行“代码块”中剩余语句,但是会继续执行“代码块”后面的语句;如果函数返回类似0,False类的Boolean假值、或者没返回值,将抛出“代码块”中的异常,那么在没有捕获异常的情况下,中断“代码块”及“代码块”之后语句的执行
with xxx as var_name:
#代码块开始
statements1
statements2
……
#代码块结束
#代码快后面的语句
statements after code block
代码演示1
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'laiyu'
class User(object):
def __init__(self, username, password):
self._username = username
self._password = password
@property
def username(self):
return self._username
@username.setter
def username(self, username):
self._username = username
@property
def password(self):
return self._password
@password.setter
def password(self, password):
self._password = password
def __enter__(self):
print('auto do something before statements body of with executed')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print('auto do something after statements body of with executed')
if __name__ == '__main__':
boy = User('shouke', 'shouke2014')
print(boy.password)
with User('shouke', '2014') as user:
print(user.password)
print('---------end-----------')
运行结果
如上,代码块运行前调用了__enter__函数,代码块运行完,自动调用了__exit__函数
代码演示2
更改上述部分代码如下,继续运行
def __exit__(self, exc_type, exc_val, exc_tb):
print('auto do something after statements body of with executed')
print('exc_type:', exc_type)
print('exc_val:', exc_val)
print('exc_tb:', exc_tb)
return False
if __name__ == '__main__':
boy = User('shouke', 'shouke2014')
print(boy.password)
with User('shouke', '2014') as user:
print(user.password)
12/0
print('after execption')
print('---------end-----------')
运行结果
对比实验:
在上述的基础上继续修改代码
def __exit__(self, exc_type, exc_val, exc_tb):
print('auto do something after statements body of with executed')
print('exc_type:', exc_type)
print('exc_val:', exc_val)
print('exc_tb:', exc_tb)
return True
if __name__ == '__main__':
boy = User('shouke', 'shouke2014')
print(boy.password)
with User('shouke', '2014') as user:
print(user.password)
12/0
print('after execption')
print('---------end-----------')
运行结果:
注意:
1、抛异常后,代码块中剩余的语句没有再继续运行
2、如果在上述的基础上,把代码中的 12/0剪切后放到password(self)中,抛出异常的异常信息是不会传递给__exit__函数的
@property
def password(self):
12/0
return self._password
运行结果如下,