对于很少使用python编写大型代码的朋友可能会忘记python还是一种面向对象的语言。在其他面向对象的语言中有构造函数、析构函数等等在生命周期不同时机自动调用的函数,python当然也是有的。除此之外,python类还有很多神奇的编写方式让对象的表现更加丰富,这些方法也被称为魔术方法。在 python中魔术方法还是比较多的,这里只挑最常用的几个来讨论一下。
1. 与生命周期有关的魔术方法
所谓生命周期是指事物产生、运行和消亡等存在过程中的若干特殊的时机。对于面向对象而言,常常被谈到的就是构造函数和析构函数。python中提供了__new__函数作为构造函数,即在对象创建时调用的函数;__del__函数作为析构函数,即在对象被销毁时调用的函数;python还提供了__init__函数在初始化的时候被调用。
从以上的演示中可以看出,构造函数__new__最先被调用,其次是__init__初始化函数,最后在对象被销毁时调用了__del__函数。知道了这些函数运行的时机就可以利用它们做一些有意义的事情。最常用的是__init__函数,一般在这个函数中进行对象成员的初始化设置;其次是__del__析构函数,一般用于关闭一些占用的资源,避免资源泄漏;最后__new__函数非常不常用,一般而言可以不用了解。
2. 与比较相关的魔术方法
在其他面向对象的语言中有操作符重载来实现对象之间的比较功能,python没有直接使用操作符重载,而是使用几个魔术函数来实现的。__gt__函数用于实现“大于号”比较,__lt__用于实现“小于号”比较,__ge__用于实现“大于等于”的比较,__le__用于实现“小于等于”的比较。
3. 与数值计算相关魔术方法
有时也有一些数值计算方面的处理需要进行简化。python提供了__abs__函数来实现取绝对值操作abs(),__pos__函数实现取“正”操作,__neg__函数实现取“负“操作。
4. 与调用相关的魔术方法
python中有一些很常用的函数,比如len,str等等,我们常常需要对一些对象使用这种操作。如果是自定义的类型,就需要实现一些魔术方法达到目的。__str__函数用于str()的调用,__hash__函数用于hash()的调用,__len__函数用于len()的调用,__call__函数用于实现以对象自己作为函数名来进行调用。熟悉了这些魔术方法之后就可以自定义更加通用的类型。
5. 与语法相关的魔术方法
循环是各种编程语言都比较常用的语法,而python中的循环就更加简便。python中的序列结构都可以直接放在for循环中进行遍历,那么自定义的类型可不可以也做成这样的呢?当然可以,就是用过实现__iter__ 和 __next__两个函数来达到目的的。
python中还有一种很常用的语法叫“with子句”,这种语法的方便之处就是使用完资源的句柄之后会自动释放,不需要显式手动close。要让自己定义的数据类型能够在这样的语法场景下使用就需要实现__enter__和__exit__两个函数。其中__enter__函数是在with子句创建的时候调用的,而__exit__函数就是在with子句结束时自动调用来释放占用的资源。
到此,一些常用的魔术方法就介绍完毕。对于python的初学者而言,应该是会有一些启发作用。但是python中的魔术方法远不止于此,对于想要了解更多魔术方法的朋友,本文也可以起一个抛砖引玉的作用。本文的notebook版本共享在GitHub上,感兴趣的朋友可以在GitHub上cnbluegeek/notebook仓库下载。