摘要:自定義向量類型從自定義向量類型入手寫出符合風(fēng)格的對象,這離不開特殊方法的支持。將對象定為不可變的通過使用兩個前導(dǎo)下劃線。程序員約定使用一個下劃線前綴編寫受保護(hù)的屬性即,他們認(rèn)為應(yīng)該使用命名約定來避免意外覆蓋屬性。
導(dǎo)語:本文章記錄了本人在學(xué)習(xí)Python基礎(chǔ)之面向?qū)ο笃闹攸c知識及個人心得,打算入門Python的朋友們可以來一起學(xué)習(xí)并交流。
本文重點:
1、掌握編寫Pythonic code背后常用的特殊方法;一、自定義具有Python風(fēng)格的類
2、掌握可擴(kuò)展的格式化輸出方法;
3、了解可散列對象的設(shè)置以及節(jié)省內(nèi)存的__slots__對象。
自定義的向量類需要支持基本的輸出,迭代,求模。
1、自定義向量類型從自定義向量類型入手寫出符合Python風(fēng)格的對象,這離不開特殊方法的支持。
我們期望的自定義向量類型應(yīng)支持的基本功能:
構(gòu)造,__init__
輸出,__repr__和__str__
迭代,__iter__
求模,__abs__
轉(zhuǎn)化為字節(jié)序列,__bytes__
代碼實現(xiàn)如下:
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)))2、使用一個類方法實現(xiàn)備選構(gòu)造方法
我們能將實例轉(zhuǎn)化為字節(jié)序列,那么也應(yīng)構(gòu)造一個將實例轉(zhuǎn)化為字節(jié)序列的方法。
@classmethod def frombytes(cls,seqs): typecode=chr(seqs[0]) memv=memoryview(seqs[1:]).cast(typecode) return cls(*memv)
memoryview是泛化和去數(shù)學(xué)化的數(shù)組。
3、classmethod和staticmethod兩個裝飾器classmethod:定義操作類而不是操作實例的方法,類方法的第一個參數(shù)是類本身而不是實例。最常見的用途是定義備選構(gòu)造方法(返回cls(*))
staticmethod:是普通的函數(shù),只是碰巧在類的定義體中,而不是在模塊層定義。
二、格式化顯示 1、擴(kuò)展內(nèi)置的format函數(shù)通過改寫format背后的__format__可以寫出可擴(kuò)展的格式。
實例1:實現(xiàn)format對向量類的處理
def __format__(self,fmt_spec=""): components=(format(v,fmt_spec)for v in self) return "({},{})".format(*components)
實例2:通過尾部自定義格式代碼p實現(xiàn)將直角坐標(biāo)向量轉(zhuǎn)化為極坐標(biāo)向量。
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,并進(jìn)行對應(yīng)的格式處理。
三、將對象變?yōu)榭缮⒘械?/b>目前的向量是不可散列的,而可散列對象需要滿足:
(1)支持hash()函數(shù),并且通過hash()得到的散列值是不變的; (2)支持通過__eq__()方法來檢測相等性; (3)若a==b為真,則hash(a)=hash(b)也為真。
所以我們需要把對象定為不可變,然后自定義__hash__。
1、將對象定為不可變的通過使用兩個前導(dǎo)下劃線。將屬性標(biāo)記為私有的。
@property def x(self): return self.__x @property def y(self): return self.__y2、自定義__hash__()
使用異或運算符實現(xiàn)。
def __hash__(self): return hash(self.x)^hash(self.y)四、其它 1、只讀屬性的設(shè)置
私有屬性的設(shè)置只是避免修改方法意外訪問不應(yīng)更改的值,而無法防止有意的改動。
通過__dict__屬性可以查詢Python如何存儲向量的屬性名,然后只要編寫a._Vector2d__x=5這樣的代碼就會惡意賦值。
Python程序員約定使用一個下劃線前綴編寫“受保護(hù)”的屬性即self._x,他們認(rèn)為應(yīng)該使用命名約定來避免意外覆蓋屬性。
2、利用__slots__節(jié)省內(nèi)存默認(rèn)情況下,Python在各個實例中名為__dict__的字典中儲存實例屬性,相應(yīng)地會消耗大量內(nèi)存。
通過__slots__類屬性,并讓解釋器把實例屬性存儲在元組中,可以節(jié)省大量內(nèi)存。
class Vector2d: __slots__ = ("__x","__y") typecode="d" #其他方法實現(xiàn)省略
使用__slots__應(yīng)注意的問題:
__slots__無法從超類繼承而來,每個子類都需要定義__slots__屬性;
實例只能擁有__slots__中列出的屬性,除非把"__dict__"加入到__slots__中(這樣做就失去了節(jié)省內(nèi)存的初衷)
如果不把"weakref__"加入__slots__,實例就不能作為弱引用的目標(biāo)。
當(dāng)處理的實例規(guī)模較小時,禁止創(chuàng)建動態(tài)屬性或不支持弱引用是比較好的選擇。
3、覆蓋類屬性通過創(chuàng)建子類可以把繼承自父類的實例屬性覆蓋掉。
class Shortvector2d(Vector2d): typecode = "f" #其它方法實現(xiàn)省略
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/41262.html
摘要:如果需要在二元運算符周圍做換行操作,例如和,那么需要將換行操作放在前面,這條規(guī)則源于數(shù)學(xué),數(shù)學(xué)家同意在二元運算符之前換行以可提高可讀性,比較以下兩個例子。在二元運算符之前換行可以讓代碼更加具有可讀性,所鼓勵這種方式。 原文地址:How to Write Beautiful Python Code With PEP 8 作者:Jasmine Finer 翻譯:howie6879 ...
摘要:本篇繼續(xù)學(xué)習(xí)之路,實現(xiàn)更多的特殊方法以讓自定義類的行為跟真正的對象一樣。之所以要讓向量不可變,是因為我們在計算向量的哈希值時需要用到和的哈希值,如果這兩個值可變,那向量的哈希值就能隨時變化,這將不是一個可散列的對象。 《流暢的Python》筆記。本篇是面向?qū)ο髴T用方法的第二篇。前一篇講的是內(nèi)置對象的結(jié)構(gòu)和行為,本篇則是自定義對象。本篇繼續(xù)Python學(xué)習(xí)之路20,實現(xiàn)更多的特殊方法以讓...
摘要:以便于用戶理解的方式返回對象的字符串表示形式。函數(shù)會調(diào)用函數(shù),對來說,輸出的是一個有序?qū)Α4送?,還有用于支持內(nèi)置的構(gòu)造函數(shù)的方法??缮⒘袑崿F(xiàn)了方法,使用推薦的異或運算符計算實例屬性的散列值私有屬性最好用命名規(guī)則來實現(xiàn)這種方式有好有壞 絕對不要使用兩個前導(dǎo)下劃線,這是很煩人的自私行為。——Ian Bicking 對象表示形式 repr() 以便于開發(fā)者理解的方式返回對象的字符串表示形式...
摘要:一基本的序列協(xié)議首先,需要就維向量和二維向量的顯示模的計算等差異重新調(diào)整。假設(shè)維向量最多能處理維向量,訪問向量分量的代碼實現(xiàn)如下若傳入的參數(shù)在備選分量中可進(jìn)行后續(xù)處理判斷分量的位置索引是否超出實例的邊界不支持非法的分量訪問,拋出。 導(dǎo)語:本文章記錄了本人在學(xué)習(xí)Python基礎(chǔ)之面向?qū)ο笃闹攸c知識及個人心得,打算入門Python的朋友們可以來一起學(xué)習(xí)并交流。 本文重點: 1、了解協(xié)議的...
摘要:函數(shù)建立函數(shù)在中,規(guī)定了一種定義函數(shù)的格式,下面的舉例就是一個函數(shù),以這個函數(shù)為例來說明定義函數(shù)的格式和調(diào)用函數(shù)的方法。返回值所謂返回值,就是函數(shù)向調(diào)用函數(shù)的地方返回的數(shù)據(jù)。 函數(shù) 建立函數(shù) 在Python中,規(guī)定了一種定義函數(shù)的格式,下面的舉例就是一個函數(shù),以這個函數(shù)為例來說明定義函數(shù)的格式和調(diào)用函數(shù)的方法。 def add_function(a, b): #冒號必須 c = ...
閱讀 3268·2021-09-29 09:34
閱讀 3617·2021-09-10 10:51
閱讀 2013·2021-09-10 10:50
閱讀 7019·2021-08-12 13:31
閱讀 3059·2019-08-30 15:54
閱讀 1682·2019-08-30 15:44
閱讀 1484·2019-08-29 12:26
閱讀 2714·2019-08-26 18:36