什么是 Python Data Model?
Python Data Model 為自定義的數(shù)據(jù)類型(通過 Class)提供與 Python 內(nèi)建類型一致的接口。
實(shí)現(xiàn)方法是:在類中定義一些特殊的方法,比如 __add__()
;當(dāng)開發(fā)者調(diào)用 len(object)
時(shí),python 解析器將執(zhí)行 object.__len__()
作用:使所有 Python 對(duì)象擁有一致的接口浓利。
實(shí)現(xiàn):通過特殊的語法 調(diào)用 對(duì)象中的特殊方法
例子:object[key]
--> object.__getitem__(key)
__getitem__
, __len__
目標(biāo):實(shí)現(xiàn)類的 __getitem__()
和 __len__()
方法
Python 特性補(bǔ)充
collections.namedtuple:可用于創(chuàng)建沒有方法的對(duì)象
>>> import collections
# 坐標(biāo)軸上的一點(diǎn)
>>> Point = collections.namedtuple('Point', ['x', 'y'])
>>> p1 = Point(5, 10)
>>> p2 = Point(x=50, y=100)
>>> repr(p1)
'Point(x=5, y=10)'
# 訪問元組中的項(xiàng)
# 通過項(xiàng)名
>>> p1.x
5
>>> p1.y
10
# 通過索引
>>> p1[0]
5
>>> p1[1]
10
# 解包
>>> x, y = p1
>>> x
5
>>> y
10
>>> p1
Point(x=5, y=10)
namedtuple
# 根據(jù)字符串創(chuàng)建列表
>>> list("ABC")
['A', 'B', 'C']
>>> 'A B C'.split()
['A', 'B', 'C']
# 列表相加
>>> [1, 2, 3]+list("ABC")
[1, 2, 3, 'A', 'B', 'C']
例子:撲克牌
import collections
class FrenchDeck:
'''一副撲克牌'''
# 一張撲克牌
# rank: 號(hào)碼
# suit: 花色
Card = collections.namedtuple('Card', ['suit', 'rank'])
suits = 'spades diamonds clubs hearts'.split()
ranks = [i for i in range(2, 11)] + list('JQKA')
def __init__(self):
self._card = [self.Card(suit, rank) for suit in self.suits
for rank in self.ranks]
def __len__(self):
'''卡牌的數(shù)量(數(shù)組的長(zhǎng)度'''
return len(self._card)
def __getitem__(self, positon):
'''獲取一張卡牌(數(shù)組中的一個(gè)元素)
* 支持索引
* 支持切分
* 支持迭代
'''
return self._card[positon]
In [1]: import Poker
In [3]: poker = Poker.FrenchDeck()
In [4]: len(poker)
Out[4]: 52
In [5]: poker[1]
Out[5]: Card(suit='spades', rank=3)
In [6]: poker[0]
Out[6]: Card(suit='spades', rank=2)
# 前3張牌
In [11]: poker[:3]
Out[11]:
[Card(suit='spades', rank=2),
Card(suit='spades', rank=3),
Card(suit='spades', rank=4)]
# 隨機(jī)選取一張撲克牌
In [8]: import random
In [10]: random.choice(poker)
Out[10]: Card(suit='diamonds', rank='Q')
好處
- 擁有和 Python 內(nèi)建類型一致的 API (
len
) - 獲得 Python 特性:切片,迭代
- 獲得 Python 標(biāo)準(zhǔn)庫支持:
reversed
,sorted
,random.choice
注意
- 自己不要使用
__foo__
的變量名钞速,它們使保留給這些特殊方法/變量使用的 - 除了 直接調(diào)用父類的
__init__
方法外贷掖,一般不直接調(diào)用這些特殊的方法,而是使用len
foo[0]
模擬數(shù)值計(jì)算
- + :
__add__
- * :
__mul__
- abs():
__abs__
當(dāng)穿給 __add__
的兩個(gè)參數(shù)的類型不同時(shí)渴语,其順序要符合定義時(shí)的順序苹威;
或者可以使用 __radd__
方法
布爾運(yùn)算
bool(objct)
返回 True 或 False
當(dāng)調(diào)用 bool()
時(shí):
- python 解析器嘗試調(diào)用對(duì)象的
__bool__
方法 -
__bool__
未定義時(shí),參數(shù)調(diào)用__len__
方法:0 為 False驾凶,其他為 True - 如果
__bool__
和__len__
都為定義牙甫,對(duì)象將永遠(yuǎn)被視為 True
字符串帶表
-
__repr__
: 用于 debug,代表一個(gè)對(duì)象调违。應(yīng)盡可能地還原構(gòu)造對(duì)象的樣子窟哺,比如Point(1, 2)
-
__str__
:用于展示給用戶看,執(zhí)行print(object)
時(shí)調(diào)用此方法翰萨;若未實(shí)現(xiàn)該方法,會(huì)調(diào)用__repr__
- 如果只實(shí)現(xiàn)一個(gè)方法糕殉,選擇
__repr__