Python __exit__,__enter__函数with语句的组合应用

时间:2023-03-10 02:19:11
Python __exit__,__enter__函数with语句的组合应用

__exit____enter__函数with语句的组合应用

 

by:授客 QQ1033553122

简介

设计对象类时,我们可以为对象类新增两个方法,一个是__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-----------')
 
运行结果
Python __exit__,__enter__函数with语句的组合应用
Python __exit__,__enter__函数with语句的组合应用
如上,代码块运行前调用了__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-----------')
 
运行结果
Python __exit__,__enter__函数with语句的组合应用
Python __exit__,__enter__函数with语句的组合应用
对比实验:
在上述的基础上继续修改代码
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-----------')
 
运行结果:
Python __exit__,__enter__函数with语句的组合应用
Python __exit__,__enter__函数with语句的组合应用
注意:
1、抛异常后,代码块中剩余的语句没有再继续运行
2、如果在上述的基础上,把代码中的 12/0剪切后放到password(self)中,抛出异常的异常信息是不会传递给__exit__函数的
@property
def password(self):
12/0
return self._password
 
运行结果如下,
Python __exit__,__enter__函数with语句的组合应用Python __exit__,__enter__函数with语句的组合应用