python读书笔记2000_流畅的Python读书笔记
特殊方法的存在是為了Python解釋器調用的,你自己并不需要去調用他們,比如說my_object.len()這種寫法是沒有的,應該使用len(my_object)。在使用len(my_object)的時候,如果my_object是一個自定義類的對象,那么Python會自己去調用其中你實現的len方法。
1.2 如何使用特殊方法
接下來進入1.2節的學習,承接概要我們可以知道自定義類中特殊方法的調用寫法,那么如果是Python內置的類型,比如列表(list)、字符串(str)、字節序列(bytearray)等,那么CPython會抄個近路,len實際上會直接返回PyVarObject里的ob_size屬性。PyVarObject是表示內存中長度可變的內置對象的語言結構體。直接讀取這個值比調用一個方法快很多。
很多時候,特殊方法的調用是隱式的,比如for i in x:這個語句,背后其實用的是iter(x),而這個函數的背后則是x.iter()方法,當然前提是這個方法在x中被實現了。
通常除非有大量元編程存在,否則直接調用特殊方法的頻率會遠低于去實現他們的次數。唯一的例外可能是init方法,目的是在你自己的字類的init方法中調用超類的構造器。通過內置的函數(例如len、str、iter等等)來使用特殊方法是最好的選擇。這些內置函數不僅會調用特殊方法,而且對于內置類來說,他們速度更快。
1.2.1 模擬數值類型
利用特殊方法,可以讓自定義對象通過加號“+”(或是別的運算符)進行運算。
我們首先實現一個二維向量(vector)類
示例 1-2 一個簡單的二維向量類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)
接下來對類里面的特殊方法進行操作
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
這里使用+運算符得到的結果也是一個向量,abs函數是一個內置函數,如果輸入的是整數或者浮點數,他返回的是輸入值的絕對值,如果輸入的是復數,那么返回這個復數的模。為了保持一致性,我們的API在碰到abs函數的時候,也應該返回該向量的模。
使用*運算符來實現向量的標量乘法(即向量與數的乘法,得到的結果向量的方向與原向量一致,模變大),接下來看看每個特殊方法的實現。
1.2.2 字符串表示形式
Python有一個內置的函數叫repr,它能把一個對象用字符串的形式表達出來以便辯認,這就是“字符串表示形式”。repr就是用過repr這個特殊方法來得到一個對象的字符串形式的。如果沒有實現repr,當我們在控制臺打印一個向量的實例時,得到的字符串可能會是。repr
交互式控制臺和調試程序(debugger)用repr函數來獲取字符串表示形式;在老的使用%符號的字符串格式中,這個函數返回的結果用來代替%r所代表的對象;同樣str.format函數所使用的新式字符串格式化語法也是利用了repr,才!r字段變成字符串
在repr的實現中,我們用到了%r來獲取對象各個屬性的標準字符串表示形式,它暗示了一個關鍵:Vector(1,2)和Vector(‘1’,’2’)是不一樣的,后者在我們的定義中會報錯,因為向量對象的構造函數只接受數值,不接受字符串。
repr和str的區別在于,后者是在str()函數被使用,或是在用print函數打印一個對象的時候才被調用的,并且它返回的字符串對終端用戶更友好。(%s對應于str()處理后的對象,%r對應于repr()處理后的對象)
1.2.3 算術運算符
通過add和mul,示例1-2為向量類帶來了+和*這兩個算術運算符,這兩個方法中的返回值都是新創建的向量對象,被操作的兩個向量(self或other)還是原封不動,代碼里只是讀取了它們的值。中綴運算符的基本原則就是不改變操作對象,而是產出一個新的值。
1.2.4 自定義的布爾值
為了判定一個值x為真還是為假,Python會調用bool(x),這個函數只能返回True或者False。
默認情況下,我們自己定義的類的實例總被認為是真的,除非這個類對bool或者len函數有自己的實現。bool(x)的背后是調用bool()的結果,如果不存在bool方法,那么bool(x)會嘗試調用x.len()。若返回0,則bool會返回False,否則返回True。
我們自己定義的類中,bool方法的實現比較簡單,如果向量的模是0,那么返回False,其他情況返回True。
如果想讓Vector.bool更高效,可以采用這種實現:1
2def __bool__(self):
return bool(self.x or self.y)
因為只有橫坐標和縱坐標同時為0時該向量模為0,所以只要取兩坐標的“或”值,同時為0時才返回0 來代替abs到abs到平方再到平方根這些中間步驟。
總結
以上是生活随笔為你收集整理的python读书笔记2000_流畅的Python读书笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python写入数据到excel_pyt
- 下一篇: vscode python单步调试_调试