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。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32import 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.abc
module)合并了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()同样能用在自己的类上。