此筆記用于記錄《流暢的Python》一書的學(xué)習(xí)要點(diǎn)嚼松,與各位Python愛好者分享虾啦,以后每周至少更新兩章內(nèi)容,完全是基于該書的精華總結(jié)同衣,并以此監(jiān)督自己竟块,讓自己在學(xué)習(xí)python的道路一直前進(jìn)!
Python數(shù)據(jù)模型:是對(duì)Python框架的描述耐齐,規(guī)范了這門語言自身構(gòu)建模塊的接口浪秘,這些模塊包括但不限于序列、迭代器埠况、函數(shù)耸携、類和上下文管理器。(個(gè)人認(rèn)為辕翰,python的數(shù)據(jù)模型其實(shí)就是構(gòu)成我們程序猿使用的諸如序列夺衍、迭代器、函數(shù)喜命、類等框架的底層實(shí)現(xiàn)沟沙,供框架本身調(diào)用。)
python中含有大量的特殊方法(__X__)壁榕,這些特殊函數(shù)我們稱之為魔術(shù)方法或者雙下方法矛紫。在做基礎(chǔ)對(duì)象操作的時(shí)候,解釋器可能背后調(diào)用的可能就是一些特殊方法牌里。比如:obj[key]調(diào)用__getitem__方法颊咬。my_collection[key]==my_collection.__getitem__(key)。
通過一個(gè)撲克牌的例子來看看python重載特殊函數(shù)的強(qiáng)大之處:
import collections
from randomimport choice
Card = collections.namedtuple('card', ['rank', 'suit']) ? #namedtuple用來創(chuàng)建只有少量屬性,沒有方法的對(duì)象
#撲克牌類喳篇,通過該類實(shí)例化的對(duì)象擁有其他一般類型一樣的屬性敞临。
class FrenchDeck:
? ? ranks = [str(n)for nin range(2, 11)] +list('JQKA')
? ? suit ='spades diamonds clubs hearts'.split()
? ? def __init__(self):
? ? ? ? self._cards = [Card(rank, suit)for rankin self.ranksfor suitin self.suit] ? ?#_cards是一個(gè)list
? ? def __len__(self):
? ? ? ? return len(self._cards) ? 返回紙牌的總數(shù)
? ? def __getitem__(self, item):
? ? ? ? return self._cards[item] ? 返回某一張紙牌對(duì)象
>>>deck = FrenchDeck()
>>>len(deck) ? #返回52
>>>deck[0] ? #返回Card(rank='2', suit='spades')?
通過特殊方法的例子,我們知道了重載的特殊函數(shù)之后的強(qiáng)大之處麸澜⊥δ颍總結(jié)一下,特殊方法怎么使用痰憎?首先票髓,特殊方法是被python解釋器調(diào)用的,我們一般不會(huì)顯式調(diào)用铣耘,也就是一般不會(huì)my_obj.__len__()洽沟,而應(yīng)該是len(my_obj),如果自己沒有實(shí)現(xiàn)特殊函數(shù)蜗细,python回去調(diào)用默認(rèn)的特殊函數(shù)裆操。也就是說,特殊方法的調(diào)用是隱式的炉媒。
此外踪区,利用特殊方法,可以讓自定義的對(duì)象(比如類實(shí)例)通過加號(hào)"+"進(jìn)行運(yùn)算吊骤。下面我們定義一個(gè)二維向量缎岗,實(shí)現(xiàn)二維向量的運(yùn)算符計(jì)算。
from mathimport hypot
class Vector():
? ? def __init__(self, x=0, y=0):
? ? ? ? self.x = x
? ? ? ? self.y = y
#把對(duì)象以字符串的形式表達(dá)出來白粉。__str__在str()被調(diào)用或者print()被調(diào)用的時(shí)候才被調(diào)用传泊。如果沒有實(shí)現(xiàn)__str__,但是實(shí)現(xiàn)了__repr__鸭巴,那么眷细,print()打印自定義對(duì)象時(shí),調(diào)用__repr__鹃祖。
? ? def __repr__(self):
? ? ? ? return 'Vector({!r}, {!r})'.format(self.x, self.y)
? ? def __str__(self):
? ? ? ? return 'vector({!r}, {!r})'.format(self.x, self.y)
#求直角三角形斜邊長
? ? def __abs__(self):
? ? ? ? return hypot(self.x, self.y)
#判斷向量是否為真
? ? def __bool__(self):
? ? ? ? return bool(abs(self))
#兩個(gè)向量相加
? ? def __add__(self, other):
? ? ? ? x =self.x + other.x
? ? ? ? y =self.y + other.y
? ? ? ? return Vector(x, y)
#向量與某一值相乘
? ? def __mul__(self, scalar):
? ? ? ? return Vector(self.x * scalar, self.y * scalar)
#向量的長度
? ? def __len__(self):
? ? ? ? return self.x +self.y