26 Jun 2017
魔术方法(magic method)是特殊方法的昵称。例如,len(collection)背后是collection.len(),而obj[key]背后是obj.getitem(key)。
关于数据模型和魔法方法,书中的描述是:
数据模型其实是对 Python 框架的描述,它规范了这门语言自身构建模块 的接口,这些模块包括但不限于序列、迭代器、函数、类和上下文管理 器。 不管在哪种框架下写程序,都会花费大量时间去实现那些会被框架本身 调用的方法, Python 也不例外。Python 解释器碰到特殊的句法时,会使 用特殊方法去激活一些基本的对象操作,这些特殊方法的名字以两个下 划线开头,以两个下划线结尾(例如 __getitem__)。比如 obj[key] 的背后就是 __getitem__ 方法,为了能求得 my_collection[key] 的 值,解释器实际上会调用 my_collection.__getitem__(key)。 这些特殊方法名能让你自己的对象实现和支持以下的语言构架,并与之交互: - 迭代 - 集合类 - 属性访问 - 运算符重载 - 函数和方法的调用 - 对象的创建和销毁 - 字符串表示形式和格式化 - 管理上下文(即 with 块)
个人对它的理解就是,python提供了一种一致性,无论是原生的数据类型,还是我们自定义的数据类型,
只要在对象中实现了相应的魔法方法(也称为特殊方法),我们就可以使自定义的对象拥有和原生数据类型一样的属性,例如,可迭代,可测量长度等。
__getitem__,__len__首先我们先创建一个基础的类,没有__getitem__,__len__
class ChineseFistName(object): def __init__(self): super(ChineseFistName, self).__init__() self.cfn = ['zhao', 'qian', 'sun', 'li', 'zhou', 'wu', 'zheng', 'wang'] cfn = ChineseFistName() # test __getitem__ for first_n in cfn: print first_n # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # TypeError: 'ChineseFistName' object is not iterable # test __len__ print len(cfn) # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # TypeError: object of type 'ChineseFistName' has no len()
我们可以看到python抛出了类型错误,而这正是因为我们自定义的类型ChineseFistName没有__getitem__,__len__这两个特殊方法。
增加__getitem__,__len__,再次测试
class ChineseFistName(object): def __init__(self): super(ChineseFistName, self).__init__() self.cfn = ['zhao', 'qian', 'sun', 'li', 'zhou', 'wu', 'zheng', 'wang'] def __getitem__(self, position): return self.cfn[position] def __len__(self): return len(self.cfn) cfn = ChineseFistName() # test __getitem__ for first_n in cfn: print first_n zhao qian sun li zhou wu zheng wang # test __len__ print len(cfn) 8
魔法方法是被python解释器调用的,我们只能使用
len(obj),而不能使用obj.__len__(obj)