流畅的Python -- 第一章 Python的模型
[toc]
Python的模型
一摞Python风格的纸牌
1 | import collections |
- namedtuple方法用于构建一些只有属性但没有方法的简单类(比如数据库条目)
- __len__和__getitem__是Python的两个特殊方法,分别对应了len(obj)和obj[],现在对这两个方法进行了重写,FrenchDeck类的对象再调用这两个特殊方法时就会走重写的逻辑
- 由于__getitem__将[]指向了self._cards,FrenchDeck对象将支持所有[]的功能比如切片、获取首尾元素,==这里没看懂实用性在哪毕竟self._cards本身也是一个list也有这些功能==
如何使用特殊方法
上面提到的__len__和__getitem__是Python的特殊方法,这些特殊方法是给Python调节器用的,开发者不要直接去调用,而是通过len()
- 当对自定义的类使用len()方法时会去调用自定义实现的__len__;当对内置类型使用len(),那么 CPython 会抄个近路,len 实际上会直接返回 PyVarObject 里的 ob_size 属性。PyVarObject是表示内存中长度可变的内置对象的 C 语言结构体。直接读取这个值比调用一个方法要快很多
- 通常代码无需直接调用特殊方法,特例是__init__
- 通过内置函数(len、str、iter)来使用特殊方法,内置函数会有额外的优化,性能更高,后续会详细的说明
- 最好不要自行定义特殊方法,比如__foo__,当前版本该方法没有被使用,但在后续的版本中就不一定了
模拟数值类型
通过重写__add__、__mul__等特殊方法来实现一个二维向量类,直接实现+、*等操作
字符串表示形式
通过__repr__方法的重新,可以实现类似java中toString方法的效果
特殊方法一览
Python中共计有83个特殊方法,其中47个用于实现算术运算,这里不一个个全列出来了
len为什么不是一个普通方法
实用大于纯粹,之前也提到了,内置的对象实用len时能够获得更高的性能,Python也提供给了自义定类使用len的方法,在语言一致性上找到了平衡点(==这里不太理解如果把len作为一个普通方法让内置类去实现为什么就不能走性能捷径了,应该是语言结构决定的后续应该会讲==)