python's docs

1.1 magic method: getitem len


0. 什么是魔术方法?

魔术方法(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提供了一种一致性,无论是原生的数据类型,还是我们自定义的数据类型,
只要在对象中实现了相应的魔法方法(也称为特殊方法),我们就可以使自定义的对象拥有和原生数据类型一样的属性,例如,可迭代,可测量长度等。

https://docs.python.org/2/reference/datamodel.html


1. __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)