詳解Python類中的特殊方法(前后都有雙下劃線的方法)-__len__、__str__忙上、__getitem__拷呆、__iter__、__getattr__疫粥、__call__等

其他關(guān)于Python的總結(jié)文章請(qǐng)?jiān)L問:http://www.reibang.com/nb/47435944

詳解Python類中的特殊方法(前后都有雙下劃線的方法)-len茬斧、strgetitem梗逮、iter项秉、getattrcall

類中定義的一些特殊方法库糠,也就是方法名稱前后都有雙下劃線標(biāo)識(shí)的方法伙狐,都具有特殊的意義涮毫,重寫這些方法可以幫助類更好地發(fā)揮功能,這里主要介紹幾種常用的贷屎、重要的方法罢防。

我們以一個(gè)偶數(shù)類(Even)為例,其中會(huì)創(chuàng)建一個(gè)N個(gè)偶數(shù)的列表唉侄,同時(shí)創(chuàng)建一個(gè)該類的實(shí)例even

class Even:
    def __init__(self, N):
        self.N = N
        self.even_list = [2 * x for x in range(N)]

even = Even(10)

len方法

__len__方法在當(dāng) len 函數(shù)作用于該類的時(shí)候被調(diào)用咒吐,比如我們定義Even類的長(zhǎng)度就是偶數(shù)列表的個(gè)數(shù):

def __len__(self):
    return self.N

此時(shí)調(diào)用len函數(shù)作用于Even類的實(shí)例上就會(huì)調(diào)用 __len__ 方法:

print(len(even)) # 20

如果沒有定義 __len__ 方法,當(dāng)len函數(shù)作用于類的實(shí)例上時(shí)就會(huì)報(bào)錯(cuò):

TypeError: object of type 'Even' has no len()

str方法

__str__方法在當(dāng) print 函數(shù)作用于該類的時(shí)候被調(diào)用属划,比如我們繼續(xù)編寫Even類恬叹,加入__str__方法:

def __str__(self):
    return "An Even Numbers List with {} Items:\n{}".format(self.N, self.even_list)

此時(shí)調(diào)用 print(even) 就可以得到如下的結(jié)果:

An Even Numbers List with 10 Items:
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

repr方法

__repr__方法是在直接(比如解釋器中)直接調(diào)用類或者實(shí)例時(shí)被觸發(fā)的,它和__str__很像同眯,唯一不同的是沒有print操作绽昼,比如這樣調(diào)用時(shí)會(huì)觸發(fā) __repr__(Python解釋器中):

>>> even

注意上邊跟 >>> print(even) 的區(qū)別)

一般來說__repr__方法和__str__方法輸出的內(nèi)容相同,所以通承胛希可以使用簡(jiǎn)單的方式來定義__repr__方法:

__repr__ = __str__

getitem方法

__getitem__方法在對(duì)類進(jìn)行迭代時(shí)觸發(fā)硅确,而且必須傳入一個(gè)整數(shù)作為參數(shù):

def __getitem__(self, n):
    return self.even_list[n]

這樣就可以使用for循環(huán)進(jìn)行對(duì)Even類的遍歷了,或者使用 even[i] 這樣對(duì)Even類進(jìn)行索引明肮,甚至是使用切片:

for i in range(len(even)):
    print(even[i], end=' ')

print()

for e in even:
    print(e, end=' ')

print()

print(even[2:8])
print(even[8:2:-1])

可以得到輸出結(jié)果:

0 2 4 6 8 10 12 14 16 18 
0 2 4 6 8 10 12 14 16 18 
[4, 6, 8, 10, 12, 14]
[16, 14, 12, 10, 8, 6]

setitem方法

__setitem__方法是和__getitem__方法對(duì)應(yīng)的菱农,用來更改某下標(biāo)所對(duì)應(yīng)處的值,必須傳入兩個(gè)參數(shù)柿估,一個(gè)key用于指定要修改的下標(biāo)循未,一個(gè)value用于告知要修改的值:

def __setitem__(self, key, value):
    self.even_list[key] = value

這樣就可以修改類的某個(gè)索引處的值了:

print(even[0])  # 0
even[0] = 100
print(even[0])  # 100

delitem方法

__delitem__方法實(shí)現(xiàn)了del作用于類時(shí)的邏輯:

def __delitem__(self, key):
    del self.even_list[key]
    self.N = len(self.even_list)

這樣使用 del 作用與類就可以得到相應(yīng)的結(jié)果:

print(even)
del even[0:5]
print(even)

得到的結(jié)果:

An Even Numbers List with 10 Items:
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
An Even Numbers List with 5 Items:
[10, 12, 14, 16, 18]

iter方法和next方法

__iter__方法返回一個(gè)可迭代對(duì)象,供 for ... in ... 循環(huán)對(duì)類進(jìn)行迭代秫舌,同時(shí)配合__next__方法在對(duì)類使用 next 函數(shù)時(shí)調(diào)用獲取下一個(gè)迭代值的妖,并且 __next__方法中可以實(shí)現(xiàn)迭代結(jié)束后給出 StopIteration 錯(cuò)誤的邏輯。

getattr方法

__getattr__方法在類的實(shí)例試圖調(diào)用一個(gè)不存在的屬性時(shí)觸發(fā)足陨,可以對(duì)應(yīng)地返回一個(gè)屬性值或者函數(shù)羔味,也可以完成對(duì)于一些屬性拋出錯(cuò)誤的邏輯:

def __getattr__(self, item):
    if item == 'length':
        return self.N
    if item == 'get_length':
        return lambda: self.N
    raise AttributeError("Even doesn't have the attribute {}".format(item))

此時(shí)如果這樣使用類,就會(huì)得到相應(yīng)的結(jié)果:

print(even.length)  # 10
print(even.get_length())  # 10
print(even.some_other_attribute)  # AttributeError: Even doesn't have the attribute some_other_attribute

注意該方法只會(huì)處理調(diào)用不存在的屬性的情況钠右,如果屬性存在則不會(huì)到__getattr__方法中尋找

call方法

__call__方法在類的實(shí)例被調(diào)用的時(shí)候觸發(fā),還可以接收參數(shù)忘蟹,我們可以使用callable函數(shù)來判斷一個(gè)類的實(shí)例是不是可調(diào)用的飒房,callable一個(gè)沒有定義__call__方法的類的實(shí)例會(huì)返回False,反之返回True

def __call__(self):
    print("Hello, you called me: an even numbers list with {} items".format(self.N))

此時(shí)調(diào)用該類的實(shí)例:

even()
print(callable(even))

就會(huì)得到相應(yīng)的結(jié)果:

Hello, you called me: an even numbers list with 10 items
True

上述內(nèi)容的完整類的代碼

class Even:
    def __init__(self, N):
        self.N = N
        self.even_list = [2 * x for x in range(N)]

    def __len__(self):
        return self.N

    def __str__(self):
        return "An Even Numbers List with {} Items:\n{}".format(self.N, self.even_list)

    __repr__ = __str__

    def __getitem__(self, n):
        return self.even_list[n]

    def __setitem__(self, key, value):
        self.even_list[key] = value

    def __delitem__(self, key):
        del self.even_list[key]
        self.N = len(self.even_list)

    def __getattr__(self, item):
        if item == 'length':
            return self.N
        if item == 'get_length':
            return lambda: self.N
        raise AttributeError("Even doesn't have the attribute {}".format(item))

    def __call__(self):
        print("Hello, you called me: an even numbers list with {} items".format(self.N))
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末媚值,一起剝皮案震驚了整個(gè)濱河市狠毯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌褥芒,老刑警劉巖嚼松,帶你破解...
    沈念sama閱讀 222,627評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嫡良,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡献酗,警方通過查閱死者的電腦和手機(jī)寝受,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來罕偎,“玉大人很澄,你說我怎么就攤上這事⊙占埃” “怎么了甩苛?”我有些...
    開封第一講書人閱讀 169,346評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)俏站。 經(jīng)常有香客問我讯蒲,道長(zhǎng),這世上最難降的妖魔是什么肄扎? 我笑而不...
    開封第一講書人閱讀 60,097評(píng)論 1 300
  • 正文 為了忘掉前任墨林,我火速辦了婚禮,結(jié)果婚禮上反浓,老公的妹妹穿的比我還像新娘萌丈。我一直安慰自己,他們只是感情好雷则,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評(píng)論 6 398
  • 文/花漫 我一把揭開白布辆雾。 她就那樣靜靜地躺著,像睡著了一般月劈。 火紅的嫁衣襯著肌膚如雪度迂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,696評(píng)論 1 312
  • 那天猜揪,我揣著相機(jī)與錄音惭墓,去河邊找鬼。 笑死而姐,一個(gè)胖子當(dāng)著我的面吹牛腊凶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拴念,決...
    沈念sama閱讀 41,165評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼钧萍,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了政鼠?” 一聲冷哼從身側(cè)響起风瘦,我...
    開封第一講書人閱讀 40,108評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎公般,沒想到半個(gè)月后万搔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體胡桨,經(jīng)...
    沈念sama閱讀 46,646評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評(píng)論 3 342
  • 正文 我和宋清朗相戀三年瞬雹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了昧谊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,861評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡挖炬,死狀恐怖揽浙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情意敛,我是刑警寧澤馅巷,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站草姻,受9級(jí)特大地震影響钓猬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜撩独,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評(píng)論 3 336
  • 文/蒙蒙 一敞曹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧综膀,春花似錦澳迫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至讥此,卻和暖如春拢锹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背萄喳。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工卒稳, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人他巨。 一個(gè)月前我還...
    沈念sama閱讀 49,287評(píng)論 3 379
  • 正文 我出身青樓充坑,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親染突。 傳聞我的和親對(duì)象是個(gè)殘疾皇子匪傍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容