概覽
????本章的重點(diǎn)就是展示Pythonic实撒,可以理解為python編程的一種風(fēng)格,比如作者例舉的python是用len(collection) 而不是用collection.len()恳谎。
???? Pythonic的關(guān)鍵就是Python data model。作者認(rèn)為data model可以想象為對(duì)python作為一種框架的描述允青。data model定義了python語(yǔ)言中各個(gè)組成部分的接口例嘱。
???? 這些接口的定義,就是作者提到的special method(特殊方法)由境。特殊方法名首尾都是雙下劃線棚亩,例如__getitem__
。python解釋器調(diào)用特殊方法來(lái)完成基礎(chǔ)的對(duì)象操作藻肄。通過(guò)在自定義類(lèi)中實(shí)現(xiàn)特殊方法蔑舞,也可以使讓用戶(hù)的自定義類(lèi)像python基礎(chǔ)對(duì)象一樣進(jìn)行操作。
???? 如何實(shí)現(xiàn)這些特殊方法嘹屯,將是后續(xù)貫穿全書(shū)的內(nèi)容攻询。
示例
???? 下面展示了一個(gè)很Pythonic的例子,看了之后感覺(jué)自己之前的python代碼太過(guò)程語(yǔ)言化了州弟。
import collections
Card = collections.namedtuple('Card', ['rank', 'suit'])
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]
???? 通過(guò)定義了__len__
和__getitem__
就可以像操作list一樣操作FrenchDeck類(lèi)钧栖。
>>> deck = FrenchDeck()
>>> len(deck)
52
>>> deck[0]
Card(rank='2', suit='spades')
>>> deck[:3]
[Card(rank='2', suit='spades'), Card(rank='3', suit='spades'), Card(rank='4', suit='spades')]
>>> Card('Q', 'hearts') in deck
True
???? 可以通過(guò)這個(gè)例子看到,通過(guò)實(shí)現(xiàn)特殊方法可以帶來(lái)兩個(gè)好處:
- 可以讓你的類(lèi)有和標(biāo)準(zhǔn)庫(kù)一樣定義的通用接口
- 可以從python標(biāo)準(zhǔn)庫(kù)里受益
__repr__和__str__
>>> import datetime
>>> today = datetime.date.today()
>>> str(today)
'2019-01-16'
>>> repr(today)
'datetime.date(2019, 1, 16)'
>>> a = '1'
>>> str(a)
'1'
>>> repr(a)
"'1'"
- 在占位符里repr使用%r婆翔,str使用%s
- str返回的結(jié)果被用于print方法拯杠,側(cè)重于好的格式展示給終端用戶(hù)
- repr一般是能和重建對(duì)象的源代碼相匹配
- 當(dāng)
__str__
沒(méi)有實(shí)現(xiàn)的時(shí)候,python將自動(dòng)調(diào)用__repr__