PYTHON进阶

7.魔术方法(2)

2021-01-10  本文已影响0人  Stone_説

目录:
1.上下文管理对象
2.上下文管理的安全性
3.with语句
4.exit方法的参数

1.上下文管理对象

当一个对象同时出现了enter()和exit()方法,它就属于上下文管理的对象

方法                                        意义
__enter__              进入与此对象相关的上下文,如果存在该方法,with语法会把该方法的返回值作为绑定到as子句中指定的变量上
__exit__               退出与对象相关的上下文
import time

class Point:
    def __init__(self):
        print('init ~~~~~~~~~~~~~~~~~')
        time.sleep(1)
        print('init over')

    def __enter__(self):
        print('enter ~~~~~~~~~~~~~~~~~')

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('exit  ~~~~~~~~~~~~~~~~~~')

with Point() as p:
    print('in with ~~~~~~~~~~~~~~~~~~~')
    time.sleep(2)
    print('with over')

print('==== end ====')

# 运行结果
init ~~~~~~~~~~~~~~~~~
init over
enter ~~~~~~~~~~~~~~~~~
in with ~~~~~~~~~~~~~~~~~~~
with over
exit  ~~~~~~~~~~~~~~~~~~
==== end ====

实例化对象的时候,并不会调用enter,进入with语句块调用enter方法,然后执行语句体,最后离开with语句块的时候,调用exit方法。
with可以开启一个上下文运行环境,在执行前做一些准备工作,执行后做一些收尾工作。
注意:with并不开启一个新的作用域。

2.上下文管理的安全性

异常对于上下文的影响

import time

class Point:
    def __init__(self):
        print('init ~~~~~~~~~~~~~~~~~')
        time.sleep(1)
        print('init over')

    def __enter__(self):
        print('enter ~~~~~~~~~~~~~~~~~')

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('exit  ~~~~~~~~~~~~~~~~~~')

with Point() as p:
    print('in with ~~~~~~~~~~~~~~~~~~~')
    raise Exception('error')
    time.sleep(2)
    print('with over')

print('==== end ====')

# 执行结果
init ~~~~~~~~~~~~~~~~~
Traceback (most recent call last):
  File "C:/Users/dell/PycharmProjects/pythonProject/test2.py", line 17, in <module>
    raise Exception('error')
Exception: error
init over
enter ~~~~~~~~~~~~~~~~~
in with ~~~~~~~~~~~~~~~~~~~
exit  ~~~~~~~~~~~~~~~~~~
# 可以看出enter和exit照样执行,上下文管理是安全的

3.with语句

import time

class Point:
    def __init__(self):
        print('init ~~~~~~~~~~~~~~~~~')
        time.sleep(1)
        print('init over')

    def __enter__(self):
        print('enter ~~~~~~~~~~~~~~~~~')
        return  self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('exit  ~~~~~~~~~~~~~~~~~~')

f = open('animal.py')
with f as p:
    print(f)
    print(p)
    print(f is p)
    print(f == p)

# 执行结果
<_io.TextIOWrapper name='animal.py' mode='r' encoding='cp936'>
<_io.TextIOWrapper name='animal.py' mode='r' encoding='cp936'>
True
True

p = Point()
with p as f:
    print('in with---------------')
    print(p == f)
    print('with over')

print('==== end ====')

# 执行结果
init ~~~~~~~~~~~~~~~~~
init over
enter ~~~~~~~~~~~~~~~~~
in with---------------
True
with over
exit  ~~~~~~~~~~~~~~~~~~
==== end ====

with语法,会调用with后的对象的enter方法,如果有as,则将该方法的返回值赋给as子句的变量。
f = p.enter()

4. exit方法的参数

__enter__方法没有参数
__exit__方法有3个参数,__exit__(self,exc_type,exc_value,traceback)
exc_type: 异常类型
exc_value: 异常的值
tracebask: 异常的追踪信息
__exit__方法返回一个等效True的值,则压制异常,否则,继续抛出异常

例1:
存在未捕获异常

import time

class Point:
    def __init__(self):
        print('init ~~~~~~~~~~~~~~~~~')
        time.sleep(1)
        print('init over')

    def __enter__(self):
        print('enter ~~~~~~~~~~~~~~~~~')
        return  self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print(1,exc_type)
        print(2,exc_val)
        print(3,exc_tb)
        print('exit  ~~~~~~~~~~~~~~~~~~')

p = Point()
with p as f:
    print('in with--------------------')
    raise Exception('Error')
    print('with over')

print('==== end ====')

# 运行结果
init ~~~~~~~~~~~~~~~~~
init over
enter ~~~~~~~~~~~~~~~~~
in with--------------------
1 <class 'Exception'>
2 Error
3 <traceback object at 0x0000024E29255408>
exit  ~~~~~~~~~~~~~~~~~~
Traceback (most recent call last):
  File "C:/Users/dell/PycharmProjects/pythonProject/test2.py", line 22, in <module>
    raise Exception('Error')
Exception: Error

例2:
捕获异常

import time

class Point:
    def __init__(self):
        print('init ~~~~~~~~~~~~~~~~~')
        time.sleep(1)
        print('init over')

    def __enter__(self):
        print('enter ~~~~~~~~~~~~~~~~~')
        return  self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print(1,exc_type)
        print(2,exc_val)
        print(3,exc_tb)
        print('exit  ~~~~~~~~~~~~~~~~~~')

p = Point()
with p as f:
    print('in with--------------------')
    try:
        raise Exception('Error')
    except:
        print('catch my exception')
    print('with over')

# 运行结果
init ~~~~~~~~~~~~~~~~~
init over
enter ~~~~~~~~~~~~~~~~~
in with--------------------
catch my exception
with over
1 None
2 None
3 None
exit  ~~~~~~~~~~~~~~~~~~
==== end ====
上一篇 下一篇

猜你喜欢

热点阅读