Python Data Model @ 流畅的Python 01
最近时常感觉有必要重学一遍python,故开此坑。
《流畅的python》这本书也是经典必读了,就从第一章开始写笔记。这章是一个引言,主要介绍了python的special methods。
Special Methods
- Special Method是形如
__methodName__的一类方法(也叫做”dunder method”,dunder是双下划线的略称),通过实现这类方法可以使得class以一些python通用的语法来调用一些特殊函数,使得代码语法更连贯,避免在用户编写的类里同样功能的函数有多种不同名称的情况。(Meant to be called by the python interpreter, not user (the only exception being__init__()which is for invoking the initializer for user superclass))- e.g. 通过实现
__getitem__()方法,可以直接通过className[0], className[1]这样类名加方括号的形式来获取类中按照某种顺序的第N个元素(get item by index) - ✴️
__getitem__()还能让我们的类变得iterable。- 可以用
in看某个元素是否在里面 - 可以用
for遍历 - 需要sorting的话,可以创建一个函数
sort_value()用以得到某种具有顺序的值,最后用for card in sorted(deck, key=sort_value):即可按照这个函数输出的值来排序。
- 可以用
- e.g. 实现
__len__()方法就可用len(class)来获取事先定义好的某种length。import collections Card = collections.namedtuple('card', ['rank', 'suit']) #name 对应console里面的这个tuple的名字 #>>>Card('2', 'diamonds') #output: card(rank='2', suit='diamonds') class FrenchDeck: ranks = [str(n) for n in range(2, 11)] + list('JQKA') suits = 'spades diamonds clubs hearts'.split() def __init__(self): self._cards = [Card(rank, suit) for suit in self.suits for rank in self.ranks] def __len__(self): return len(self._cards) def __getitem__(self, position): return self._cards[position] #iterable >>> for card in deck: print(card) #Card(rank='2', suit='spades') #Card(rank='3', suit='spades') #Card(rank='4', suit='spades')
- e.g. 通过实现
- e.g. 模拟数值类 Emulating Numeric Types
- To build a vector type
Vector(a,b), you’ll have to implement__repr__(),__abs__(),__add__()and__mul__()
- To build a vector type
- 书中继续介绍了
__repr__()和__str__()两个special methods, 一个是展示在console,一个是展示在print里的。__repr__()is called by the repr builtin to display the string representation of the object in the console.- With repr, the console displays:
Vector(9, 12), instead of<Vector object at 0x10e100070> __str__is called by thestr()built-in and implicitly used by the print function. It should return a string suitable for display to end users.
Collection API
接下来简单介绍了Python的Collection API。所有的类都是ABC(abstract base classes)。
- 我们有top ABC,这些ABC都只有一个special method,如Iterable的
__iter__, Sized的__len__.- Interable要求支持unpacking和iteration
- Sized要求实现len
- Container要求支持
in操作符
- Collection ABC (即
collections.abcmodule)合并了Iterable, Sized和Container三个接口。 - Python不要求每个具体的类都要实现
__len__,但如果他实现了,那么他就satisfy 了Sized Interface。- 具体关系为

- 具体关系为
- 其中,三个重要的Collections是
- Sequence, 规范了list, str 这些重要的built-in;只有sequence是reversible的,因为它支持arbituary ordering,其他两个不行。dict是假order,只保留key insertion order。
- Mapping, 有
dict,collections.defaultdict等实现 - Set, 有
set和frozenset等
其它
BTW, 在CPython里,builtin types的len()其实不是一个method,它只是从C struct里面读取了一个field的值,所以len()效率很高;因为builtin需要高效的实现。现在,用户可以通过实现__len__使得len()同样能用在自己的类上。