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