Fluent Python Charpter 1.1
A Pythonic Card Deck
这个post在于介绍Python的Data Model。
书中的说法是,Data Model是framework。某些syntax或者built-in functions会触发解释器调用Python已经定义好的special methods。最直接的2个例子:
1 | 0, 1]), [0, 1].__len__() len([ |
len()
触发的是list.__len__()
,dict[key]
语法触发的就是dict.__getitem__(key)
。
这里再引用一个游戏王卡组的例子。
先用namedtuple
定义卡牌,再实例化一张青眼白龙,typename
是这类tuple
的意义, field_names
就是tuple
中对应顺序元素的意义。
1 | import collections |
然后定义有青眼白龙,黑暗魔术师和真红眼黑龙的卡组。我们还用切片的方式抽出卡组的第一张牌。
1 | class YuGiOhDeck: |
问题来了,我们抽牌不是神抽,那怎么抽卡组?所以需要写一个抽牌的method?
这个时候就体现出Data Model的好处。
1 | from random import choice |
通过查看random.choice
的源码,其实包含了三个步骤,
- 调用
len(seq)
获得序列的长度 - 产生一个
[0, length-1]
的随机整数i
seq[i]
切片
所以Data Model的好处就在于,提前定义了很多神奇的operations,我们只需要定义好它们所需要的special methods,就可以套用那些opeartions。
此外,因为我们已经定义好了__getitem__
,所以我们还能通过切片神抽。
1 | 1] deck[ |
定义好__getitem__
,意味着YuGiOhDeck
是iterable,于是reversed()
,sorted()
,in
都支持了。
1 | list(reversed(deck)) |
总结一下,我们不需要显式地定义一个新的类继承于某些已经基本的类,只需要通过定义special methods就能让我们定义的类可以使用到python的很多语言特性。