導語:本文章記錄了本人在學習Python基礎之面向對象篇的重點知識及我的心得,打算入門Python的朋友們能夠來一塊兒學習並交流。
本文重點:python
一、掌握編寫Pythonic code背後經常使用的特殊方法;
二、掌握可擴展的格式化輸出方法;
三、瞭解可散列對象的設置以及節省內存的__slots__對象。
自定義的向量類須要支持基本的輸出,迭代,求模。程序員
從自定義向量類型入手寫出符合Python風格的對象,這離不開特殊方法的支持。
咱們指望的自定義向量類型應支持的基本功能:數組
代碼實現以下:函數
import math from array import array class Vector2d: typecode='d' def __init__(self,x,y): self.x=float(x) self.y=float(y) def __str__(self): return str(tuple(self)) def __iter__(self): return (i for i in (self.x,self.y)) def __repr__(self): classname=type(self).__name__ s="{}({},{})".format(classname,*self) return s def __abs__(self): return math.hypot(self.x,self.y) def __bytes__(self): return (bytes(self.typecode,encoding='utf-8')+ bytes(array(self.typecode,self)))
咱們能將實例轉化爲字節序列,那麼也應構造一個將實例轉化爲字節序列的方法。學習
@classmethod def frombytes(cls,seqs): typecode=chr(seqs[0]) memv=memoryview(seqs[1:]).cast(typecode) return cls(*memv)
memoryview是泛化和去數學化的數組。code
classmethod:定義操做類而不是操做實例的方法,類方法的第一個參數是類自己而不是實例。最多見的用途是定義備選構造方法(返回cls(*))component
staticmethod:是普通的函數,只是碰巧在類的定義體中,而不是在模塊層定義。orm
經過改寫format背後的__format__能夠寫出可擴展的格式。
實例1:實現format對向量類的處理對象
def __format__(self,fmt_spec=''): components=(format(v,fmt_spec)for v in self) return "({},{})".format(*components)
實例2:經過尾部自定義格式代碼p實現將直角座標向量轉化爲極座標向量。繼承
def __format__(self,fmt_spec=''): if fmt_spec[-1]=="p": coord=(abs(self),self.angle()) spec=fmt_spec[:-1] components=(format(v,spec)for v in coord) outer="<{},{}>" else: coord=self components = (format(v, fmt_spec) for v in self) outer = "({},{})" return outer.format(*components)
本段代碼的重點在於判斷格式中是否存在自定義格式符p,並進行對應的格式處理。
目前的向量是不可散列的,而可散列對象須要知足:
(1)支持hash()函數,而且經過hash()獲得的散列值是不變的; (2)支持經過__eq__()方法來檢測相等性; (3)若a==b爲真,則hash(a)=hash(b)也爲真。
因此咱們須要把對象定爲不可變,而後自定義__hash__。
經過使用兩個前導下劃線。將屬性標記爲私有的。
@property def x(self): return self.__x @property def y(self): return self.__y
使用異或運算符實現。
def __hash__(self): return hash(self.x)^hash(self.y)
Python程序員約定使用一個下劃線前綴編寫「受保護」的屬性即self._x
,他們認爲應該使用命名約定來避免意外覆蓋屬性。默認狀況下,Python在各個實例中名爲__dict__的字典中儲存實例屬性,相應地會消耗大量內存。經過__slots__類屬性,並讓解釋器把實例屬性存儲在元組中,能夠節省大量內存。
class Vector2d: __slots__ = ('__x','__y') typecode='d' #其餘方法實現省略
使用__slots__應注意的問題:
當處理的實例規模較小時,禁止建立動態屬性或不支持弱引用是比較好的選擇。
經過建立子類能夠把繼承自父類的實例屬性覆蓋掉。
class Shortvector2d(Vector2d): typecode = 'f' #其它方法實現省略