特殊方法以及如何使用特殊方法?
(此篇部分摘自书籍《流畅的python》,推荐下这本书,写的挺好的)
魔法方法(dunder method)是特殊方法的昵称。有些Python开发者在提到__getitem__这个特殊方法的时候,会用诸如“下划线-下划线-getitem”这种说法,但是显然这种说法会引起歧义,因为像__x这种命名在 Python 里还有其他含义,但是如果完整地说出“下划线-下划线-getitem-下划线-下划线”,又会很麻烦。于是我跟着Steve Holden,一位技术书作者和老师,学会了“双下-getitem”(dunder-getitem)这种说法。于是乎,特殊方法也叫双下方法(dunder method)
首先明确一点,特殊方法的存在是为了被Python解释器调用的,你自己
并不需要调用它们,也就是说没有my_object.__len__()这种写法,而应该使用len(my_object)。在执行len(my_object)的时候,如果my_object是一个自定义类的对象,那么 Python 会自己去调用其中由你实现的__len__方法。
然而如果是Python内置的类型,比如列表(list)、字符串(str)、字节序列(bytearray)等,那么CPython会抄个近路,__len__实际上会直接返回PyVarObject里的ob_size属性。PyVarObject是表示内存中长度可变的内置对象的C 语言结构体。直接读取这个值比调用一个方法要快很多
很多时候,特殊方法的调用是隐式的,比如for i in x:这个语句,背后其实用的是iter(x),而这个函数的背后则是x.__iter__()方法。当然前提是这个方法在x中被实现了
接着看个例子
#创建公司类
class Company(object):
def __init__(self, employ_list):
self.employee = employ_list
company = Company(['tom', 'bob', 'jane'])
employee =company.employee
for em in employee:
print(em)
#结果
tom
bob
jane
class Company(object):
def __init__(self, employ_list):
self.employee = employ_list
def __getitem__(self, item):
return self.employee[item]
company = Company(['tom', 'bob', 'jane'])
for em in company:
print(em)
#结果
tom
bob
jane
第一个例子使我们正常创建类的过程,第二个例子中我们加入了特殊方法__getitem__,当for循环遍历company对象时会调用__getitem__。对于__getitem__这个方法既不属于Company类,也不继承object而来,可以理解为独立的存在,当我们往类中加入特殊方法后会增强类的类型,在这里我们加入__getitem__,使Company具有序列类型的功能,我们也可以对company这个对象进行切片操作,这就是特殊方法的神奇之处,所以也被叫做魔法方法