Python类的内置函数及上下文管理

Posted by heleiqiu on July 13, 2021

Python类的内置函数

内置函数 说明
__init__(self,...) 初始化对象,在创建新对象时调用
__enter__(self,...) 当出现with语句的时候,对象的__enter__()方法被触发
__exit__(self,...) with语句块里面的代码执行后,对象的__exit__()方法被触发进行清理工作
__del__(self) 释放对象,在对象被删除之前调用
__new__(cls,*args,**kwd) 生成类实例,在__init__()之前被调用,详细理解可参考详解Python中的__init__和__new__
__call__(self,*args) 把实例对象作为函数调用,可以在对象创建时直接返回__call__()的内容。使用该方法可以模拟静态方法
__str__(self) 用于表示对象代表的含义,返回一个字符串,在使用print语句时被调用,也可以通过函数str()触发__str__()的执行
__getitem__(self,key) 获取序列的索引key对应的值,等价于seq[key]
__len__(self) 在调用内联函数len()时被调用
__cmp__(stc,dst) 比较两个对象srcdst
__getattr__(s,name) 获取属性的值
__setattr__(s,name,value) 设置属性的值
__delattr__(s,name) 删除name属性
__getattribute__() __getattribute__()功能与__getattr__()类似,但__getattribute__()能提供更好的控制,代码更健壮
__gt__(self,other) 判断self对象是否大于other对象
__lt__(slef,other) 判断self对象是否小于other对象
__ge__(slef,other) 判断self对象是否大于或者等于other对象
__le__(slef,other) 判断self对象是否小于或者等于other对象
__eq__(slef,other) 判断self对象是否等于other对象

Python类的上下文管理

编写上下文管理器的主要原理是你的代码会放到with语句块中执行。 为了让一个对象兼容with语句,需要实现__enter__()__exit__()方法。当出现with语句的时候,对象的__enter__()方法被触发,它返回的值(如果有的话)会被赋值给as声明的变量。然后with语句块里面的代码开始执行。 最后__exit__()方法被触发进行清理工作。

示例1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class MyClass:

    def __init__(self):
        print("init")
 
    def __enter__(self):
        print("enter")
        return self

    def out(self):
        print("out")
        
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("exit")

    def __del__(self):
        print("del")
 

if __name__ == '__main__':

    myClass = MyClass()
    print("st")
    with myClass as MC:
        MC.out()
        print("hi")
    print("ed")

init
st
enter
out
hi
exit
ed
del

不管with代码块中发生什么,上面的控制流都会执行完,就算代码块中发生了异常也是一样的。 事实上,__exit__()方法的第三个参数包含了异常类型、异常值和追溯信息(如果有的话)。__exit__()方法能自己决定怎样利用这个异常信息,或者忽略它并返回一个None值。 如果__exit__()返回True,那么异常会被清空,就好像什么都没发生一样,with语句后面的程序继续在正常执行。

在需要管理一些资源比如文件、网络连接和锁的编程环境中,使用上下文管理器是很普遍的。 这些资源的一个主要特征是它们必须被手动的关闭或释放来确保程序的正确运行。 例如,如果你请求了一个锁,那么你必须确保之后释放了它,否则就可能产生死锁。 通过实现 __enter__()__exit__()方法并使用with语句可以很容易的避免这些问题, 因为__exit__()方法可以让你无需担心这些了。