Python魔法方法指南
--11:33更新--
很多人想要我的一份学习笔记,所以在魔法指南之前,我放上我自己学习过程中提炼的一些知识点和自己的感悟,如果不想看我的笔记可以直接跳过。
从入门到进阶,一个很重要的点就是Python中的魔法方法,魔法方法就是可以给你的类增加魔力的特殊方法,如果你的对象实现了这些方法中的某一个,那么这个方法就会在特殊的情况下被 Python 所调用,你可以定义自己想要的行为,而这一切都是自动发生的。它们经常是两个下划线包围来命名的(比如 __init__/__new__等等),Python的魔法方法是非常强大的。
如果你学习过Java,那你会发现Python中的魔法方法像是Java中的重载,Python中的魔法方法可以理解为:对类中的内置方法的重载,注意这里不是重写。
举个例子,Python中有个比较操作符==用来比较两个变量的大小,而这个操作符是通过内置函数__eq__来实现的,所以我们只需要通过改变这个内置函数代码,就可以改变重新定义这个操作符的行为。
我们定义一个类Word,继承自str类,现需要重新定义该类的操作符==,使这个操作符用来判断两个字符串长度是否相等,而不是通过字母顺序判断两个字符串是否相等。注意该变化只适用于Word类,而不适用于其它类。
再举个例子:Python中的__new__方法是对象实例化时调用的个方法,该方法仅读取一个cls参数后再把其他参数都传给用于指明对象初始化行为的__init__方法,也就是说我们可以在一个对象初始化之前进行其他操作,比如检查是否合法等;而另一个方法__del__可以用来销毁对象,定义了对象被垃圾回收的行为,我们可以利用该方法进行资源回收等操作。
我们可以通过重写__new__方法实现一个单例模式,在每次实例化之前检查该对象是否有已有实例。
通过这两个例子相信你已经对Python的魔法方法比较理解了,但是Python中的魔法方法远不止两三个,而在官方文档中,也没有一个比较详细的归纳,所以这里参考译文(在此文的后部分)做一个简单的汇总,希望大家可以根据这个汇总的表单对其中的魔法方法进行尝试,下次再看到这样的用法也就不足为奇了。
由于版本等问题,以下的表格对译文的内容进行了修改、删减。
以上是关于操作符运算符的方法,我们很少会改变这些魔法方法除非你真的需要改变他们,当然还有一些我们可能会用到的:
1、__str__/__repr__
__str__定义对类的实例调用str()时的行为。而__repr__定义对类的实例调用repr()的行为,这两者的区别就是repr面向机器,str面向人。定义类的输出的时候经常会使用这两个其中的魔法。
2、__getattr__/__setattr__/__del__attr
使用这三个方法你可以随时修改、删除、添加类属性或值,是不是觉得大吃一惊?
Python中魔法函数常用的大体如上,也还有一些没有提到,你可以继续往下阅读。
以下是译文的原文正文
原作者:Rafe Kettler ; 翻译:hit9
原文地址:11. (译)Python魔法方法指南
1、简介
本指南归纳于我的几个月的博客,主题是 魔法方法 。
什么是魔法方法呢?它们在面向对象的Python的处处皆是。它们是一些可以让你对类添加“魔法”的特殊方法。 它们经常是两个下划线包围来命名的(比如 __init__ , __lt__ )。但是现在没有很好的文档来解释它们。 所有的魔法方法都会在Python的官方文档中找到,但是它们组织松散。而且很少会有示例(有的是无聊的语法描述, 语言参考)。
所以,为了修复我感知的Python文档的缺陷,我开始提供更为通俗的,有示例支持的Python魔法方法指南。我一开始 写了一些博文,现在我把这些博文总起来成为一篇指南。
希望你喜欢这篇指南,一篇友好,通俗易懂的Python魔法方法指南!
2、构造方法
我们为熟知的基本的魔法方法就是 __init__ ,我们可以用它来指明一个对象初始化的行为。然而,当我们调用 x = SomeClass() 的时候, __init__ 并不是个被调用的方法。事实上,个被调用的是 __new__ ,这个 方法才真正地创建了实例。当这个对象的生命周期结束的时候, __del__ 会被调用。让我们近一步理解这三个方法:
-
__new__(cls,[...)
__new__ 是对象实例化时个调用的方法,它只取下 cls 参数,并把其他参数传给 __init__ 。 __new__ 很少使用,但是也有它适合的场景,尤其是当类继承自一个像元组或者字符串这样不经常改变的类型的时候。我不打算深入讨论 __new__ ,因为它并不是很有用, Python文档 中 有详细的说明。
-
__init__(self,[...])
类的初始化方法。它获取任何传给构造器的参数(比如我们调用 x = SomeClass(10, ‘foo’) , __init__ 就会接到参数 10 和 ‘foo’ 。 __init__ 在Python的类定义中用的多。
-
__del__(self)
__new__ 和 __init__ 是对象的构造器, __del__ 是对象的销毁器。它并非实现了语句 del x (因此该语句不等同于 x.__del__())。而是定义了当对象被垃圾回收时的行为。 当对象需要在销毁时做一些处理的时候这个方法很有用,比如 socket 对象、文件对象。但是需要注意的是,当Python解释器退出但对象仍然存活的时候, __del__ 并不会 执行。 所以养成一个手工清理的好习惯是很重要的,比如及时关闭连接。
这里有个 __init__ 和 __del__ 的例子:
from os.path import join
class FileObject:
'''文件对象的装饰类,用来保证文件被删除时能够正确关闭。'''
def __init__(self, filepath='~', filename='sample.txt'):
# 使用读写模式打开filepath中的filename文件
self.file = open(join(filepath, filename), 'r+')
def __del__(self):
self.file.close()
del self.file
相关文章