python读书笔记2000_流畅的Python读书笔记
特殊方法的存在是為了Python解釋器調(diào)用的,你自己并不需要去調(diào)用他們,比如說(shuō)my_object.len()這種寫(xiě)法是沒(méi)有的,應(yīng)該使用len(my_object)。在使用len(my_object)的時(shí)候,如果my_object是一個(gè)自定義類的對(duì)象,那么Python會(huì)自己去調(diào)用其中你實(shí)現(xiàn)的len方法。
1.2 如何使用特殊方法
接下來(lái)進(jìn)入1.2節(jié)的學(xué)習(xí),承接概要我們可以知道自定義類中特殊方法的調(diào)用寫(xiě)法,那么如果是Python內(nèi)置的類型,比如列表(list)、字符串(str)、字節(jié)序列(bytearray)等,那么CPython會(huì)抄個(gè)近路,len實(shí)際上會(huì)直接返回PyVarObject里的ob_size屬性。PyVarObject是表示內(nèi)存中長(zhǎng)度可變的內(nèi)置對(duì)象的語(yǔ)言結(jié)構(gòu)體。直接讀取這個(gè)值比調(diào)用一個(gè)方法快很多。
很多時(shí)候,特殊方法的調(diào)用是隱式的,比如for i in x:這個(gè)語(yǔ)句,背后其實(shí)用的是iter(x),而這個(gè)函數(shù)的背后則是x.iter()方法,當(dāng)然前提是這個(gè)方法在x中被實(shí)現(xiàn)了。
通常除非有大量元編程存在,否則直接調(diào)用特殊方法的頻率會(huì)遠(yuǎn)低于去實(shí)現(xiàn)他們的次數(shù)。唯一的例外可能是init方法,目的是在你自己的字類的init方法中調(diào)用超類的構(gòu)造器。通過(guò)內(nèi)置的函數(shù)(例如len、str、iter等等)來(lái)使用特殊方法是最好的選擇。這些內(nèi)置函數(shù)不僅會(huì)調(diào)用特殊方法,而且對(duì)于內(nèi)置類來(lái)說(shuō),他們速度更快。
1.2.1 模擬數(shù)值類型
利用特殊方法,可以讓自定義對(duì)象通過(guò)加號(hào)“+”(或是別的運(yùn)算符)進(jìn)行運(yùn)算。
我們首先實(shí)現(xiàn)一個(gè)二維向量(vector)類
示例 1-2 一個(gè)簡(jiǎn)單的二維向量類1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23from math import hypot
class Vector:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __repr__(self):
return 'Vector(%r, %r)' % (self.x, self.y)
def __abs__(self):
return hypot(self.x,self.y)
def __bool__(self):
return bool(abs(self))
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)
接下來(lái)對(duì)類里面的特殊方法進(jìn)行操作
1
2
3
4
5
6
7
8
9
10
11
12
13v = Vector(3,4)
v1 = Vector(2,4)
v2 = Vector(2,1)
print(abs(v))
print(v1+v2)
print(v*3)
print(abs(v*3))
Output:
5.0
Vector(4, 5)
Vector(9, 12)
15.0
這里使用+運(yùn)算符得到的結(jié)果也是一個(gè)向量,abs函數(shù)是一個(gè)內(nèi)置函數(shù),如果輸入的是整數(shù)或者浮點(diǎn)數(shù),他返回的是輸入值的絕對(duì)值,如果輸入的是復(fù)數(shù),那么返回這個(gè)復(fù)數(shù)的模。為了保持一致性,我們的API在碰到abs函數(shù)的時(shí)候,也應(yīng)該返回該向量的模。
使用*運(yùn)算符來(lái)實(shí)現(xiàn)向量的標(biāo)量乘法(即向量與數(shù)的乘法,得到的結(jié)果向量的方向與原向量一致,模變大),接下來(lái)看看每個(gè)特殊方法的實(shí)現(xiàn)。
1.2.2 字符串表示形式
Python有一個(gè)內(nèi)置的函數(shù)叫repr,它能把一個(gè)對(duì)象用字符串的形式表達(dá)出來(lái)以便辯認(rèn),這就是“字符串表示形式”。repr就是用過(guò)repr這個(gè)特殊方法來(lái)得到一個(gè)對(duì)象的字符串形式的。如果沒(méi)有實(shí)現(xiàn)repr,當(dāng)我們?cè)诳刂婆_(tái)打印一個(gè)向量的實(shí)例時(shí),得到的字符串可能會(huì)是。repr
交互式控制臺(tái)和調(diào)試程序(debugger)用repr函數(shù)來(lái)獲取字符串表示形式;在老的使用%符號(hào)的字符串格式中,這個(gè)函數(shù)返回的結(jié)果用來(lái)代替%r所代表的對(duì)象;同樣str.format函數(shù)所使用的新式字符串格式化語(yǔ)法也是利用了repr,才!r字段變成字符串
在repr的實(shí)現(xiàn)中,我們用到了%r來(lái)獲取對(duì)象各個(gè)屬性的標(biāo)準(zhǔn)字符串表示形式,它暗示了一個(gè)關(guān)鍵:Vector(1,2)和Vector(‘1’,’2’)是不一樣的,后者在我們的定義中會(huì)報(bào)錯(cuò),因?yàn)橄蛄繉?duì)象的構(gòu)造函數(shù)只接受數(shù)值,不接受字符串。
repr和str的區(qū)別在于,后者是在str()函數(shù)被使用,或是在用print函數(shù)打印一個(gè)對(duì)象的時(shí)候才被調(diào)用的,并且它返回的字符串對(duì)終端用戶更友好。(%s對(duì)應(yīng)于str()處理后的對(duì)象,%r對(duì)應(yīng)于repr()處理后的對(duì)象)
1.2.3 算術(shù)運(yùn)算符
通過(guò)add和mul,示例1-2為向量類帶來(lái)了+和*這兩個(gè)算術(shù)運(yùn)算符,這兩個(gè)方法中的返回值都是新創(chuàng)建的向量對(duì)象,被操作的兩個(gè)向量(self或other)還是原封不動(dòng),代碼里只是讀取了它們的值。中綴運(yùn)算符的基本原則就是不改變操作對(duì)象,而是產(chǎn)出一個(gè)新的值。
1.2.4 自定義的布爾值
為了判定一個(gè)值x為真還是為假,Python會(huì)調(diào)用bool(x),這個(gè)函數(shù)只能返回True或者False。
默認(rèn)情況下,我們自己定義的類的實(shí)例總被認(rèn)為是真的,除非這個(gè)類對(duì)bool或者len函數(shù)有自己的實(shí)現(xiàn)。bool(x)的背后是調(diào)用bool()的結(jié)果,如果不存在bool方法,那么bool(x)會(huì)嘗試調(diào)用x.len()。若返回0,則bool會(huì)返回False,否則返回True。
我們自己定義的類中,bool方法的實(shí)現(xiàn)比較簡(jiǎn)單,如果向量的模是0,那么返回False,其他情況返回True。
如果想讓Vector.bool更高效,可以采用這種實(shí)現(xiàn):1
2def __bool__(self):
return bool(self.x or self.y)
因?yàn)橹挥袡M坐標(biāo)和縱坐標(biāo)同時(shí)為0時(shí)該向量模為0,所以只要取兩坐標(biāo)的“或”值,同時(shí)為0時(shí)才返回0 來(lái)代替abs到abs到平方再到平方根這些中間步驟。
總結(jié)
以上是生活随笔為你收集整理的python读书笔记2000_流畅的Python读书笔记的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
                            
                        - 上一篇: python写入数据到excel_pyt
 - 下一篇: 我们家的男子汉原文赏析