您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)Python常用的魔法方法是什么,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
Python的魔法方法會(huì)在特定的情況下自動(dòng)調(diào)用,且他們的方法名通常被雙下劃線包裹,之前我們學(xué)習(xí)的構(gòu)造函數(shù)和析構(gòu)函數(shù)就屬于魔法方法
Python中同樣有運(yùn)算符重載,其實(shí)所有的運(yùn)算符都是使用了對(duì)應(yīng)的魔法方法來處理的對(duì)象的,魔法方法對(duì)應(yīng)的操作符如下
我們來舉一個(gè)簡單的例子
class A: def __init__(self,x): self.x = x def __add__(self,other): return int(self.x)+int(other.x) a = A(3.3) b = A(5.2) print(a+b)
類似的還有反運(yùn)算重載和增量復(fù)制運(yùn)算,用處較少,不再解釋
__str__(self)
:返回值是str類型的,當(dāng)我們需要以字符串的形式輸出對(duì)象時(shí)(調(diào)用print時(shí)),就會(huì)自動(dòng)調(diào)用該方法,舉個(gè)例子
class A: def __str__(self): return '我真帥' a = A() print(a)# 我真帥
__repr__(self)
:返回值是str類型的,當(dāng)我們直接在shell中輸入對(duì)象名并按下回車,就會(huì)自動(dòng)調(diào)用該方法,他也有和__str__
一樣的功能,但如果兩者你都重寫了,在使用print時(shí),__str__
的優(yōu)先級(jí)高,__repr__
是給機(jī)器看的,__str__
是給人看的,舉個(gè)例子
>>> class A: def __str__(self): return '我真帥' def __repr__(self): return '我是世界第一帥' >>> a = A() >>> a 我是世界第一帥 >>> print(a) 我真帥
__getattr__(self, name)
:定義當(dāng)用戶試圖獲取一個(gè)不存在的屬性時(shí)的行為,其中name是屬性名,是一個(gè)字符串,下同
__getattribute__(self, name)
:定義當(dāng)該類的屬性被訪問時(shí)的行為,該方法默認(rèn)返回該屬性的值
__setattr__(self, name, value)
:定義當(dāng)一個(gè)屬性被設(shè)置時(shí)的行為,value是給該屬性的值
__delattr__(self, name)
:定義當(dāng)一個(gè)屬性被刪除時(shí)的行為
例如:
class A: def __init__(self): self.id = "Pyhon" def __getattr__(self,name): print(name+"這個(gè)屬性不存在") def __getattribute__(self,name): print("我訪問了"+name+"這個(gè)屬性") return super().__getattribute__(name) def __setattr__(self,name,value): print("將屬性"+name+"置為"+value) super().__setattr__(name,value) def __delattr__(self,name): print("將屬性"+name+"刪除了"); super().__delattr__(name) def fun(self): pass a = A() a.name a.name = "老師" del a.name a.fun() # output: # 將屬性id置為Pyhon # 我訪問了name這個(gè)屬性 # name這個(gè)屬性不存在 # 將屬性name置為老師 # 將屬性name刪除了 # 我訪問了fun這個(gè)屬性
結(jié)果可以看出,當(dāng)我們?cè)L問一個(gè)屬性的時(shí)候,先是調(diào)用了__getattribute__
,如果該屬性不存在,則再調(diào)用__getattr__
使用這幾個(gè)的方法的時(shí)候,要注意不要陷入無限遞歸,運(yùn)算符重載的時(shí)候也容易犯這種錯(cuò)誤,例如下面的錯(cuò)誤
class A: def __init__(self): self.id = "Pyhon" def __setattr__(self,name,value): print("將屬性"+name+"置為"+value) if(name == "id"): self.id = value a = A()
執(zhí)行這段程序的時(shí)候?qū)⑾萑霟o限遞歸,原因是在__setattr__
中,直接給self對(duì)象的屬性賦值,而這又會(huì)調(diào)用__setattr__
方法。
所以在__setattr__
中,我們通常會(huì)使用父類的__setattr__
方法來給self對(duì)象的屬性賦值,這不會(huì)陷入無限遞歸,其他幾個(gè)方法和運(yùn)算符重載也是同理,上面程序訂正后如下
class A: def __init__(self): self.id = "Pyhon" def __setattr__(self,name,value): print("將屬性"+name+"置為"+value) if(name == "id"): super().__setattr__(name,value) a = A() # output # 將屬性id置為Pyhon
__get__(self, instance, owner)
:通過其他實(shí)例對(duì)象來訪問該類的實(shí)例對(duì)象時(shí)會(huì)調(diào)用該方法,返回該實(shí)例對(duì)象的引用。其中instance是訪問該對(duì)象的實(shí)例對(duì)象的引用,下同,owner是訪問該對(duì)象的類對(duì)象
__set__(self, instance, value)
:通過其他實(shí)例對(duì)象來給該類的實(shí)例對(duì)象賦值時(shí)會(huì)調(diào)用該方法。其中value是給該對(duì)象賦的值
__delete__(self, instance)
:通過其他實(shí)例對(duì)象來刪除該類的實(shí)例對(duì)象時(shí)會(huì)調(diào)用該方法
class Fit: def __init__(self): self.height = 180 self.weight = 80 def __get__(self,instance,owner): print("get:",instance,owner) return [self.height,self.weight] def __set__(self,instance,value): print("set:",instance,value) self.height = value self.weight = value/2 def __delete__(self,instance): del self.height del self.weight print("delete:",instance) class Test: fit = Fit() t = Test() print (t.fit) t.fit = 190 del t.fit # output: # get: <__main__.Test object at 0x0000023EFFA738C8> <class '__main__.Test'> # [180, 80] # set: <__main__.Test object at 0x0000023EFFA738C8> 190 # delete: <__main__.Test object at 0x0000023EFFA738C8>
通常情況下,上面幾個(gè)魔法方法,當(dāng)我們需要定義一個(gè)屬性,且希望可以直接對(duì)該屬性進(jìn)行相應(yīng)的操作,而不是通過調(diào)用方法的方式來進(jìn)行操作時(shí),我們可以定義一個(gè)該屬性的類,實(shí)現(xiàn)上面幾個(gè)魔法方法,將需要用到的屬性作為其實(shí)例對(duì)象,這樣就完成了,例如上面的Fit,其實(shí)就是體型類,而Test中有一個(gè)體型屬性叫fit,我們?cè)贔it中定義了一些對(duì)Fit的實(shí)例對(duì)象操作時(shí)執(zhí)行的操作。
__len__(self)
:定義當(dāng)該類的實(shí)例對(duì)象被len()調(diào)用時(shí)的行為
__getitem__(self, key)
:定義獲取該類的實(shí)例對(duì)象中指定元素的行為,也就是說執(zhí)行self[key]時(shí)的行為
__setitem__(self, key, value)
:定義設(shè)置該類的實(shí)例對(duì)象中指定元素的行為,相當(dāng)于self[key] = value
__delitem__(self, key)
:定義刪除該類的實(shí)例對(duì)象中指定元素的新聞,相當(dāng)于del self[key]
class CountList: def __init__(self,*args): self.values = [x for x in args]#這是一個(gè)列表推導(dǎo)式,把a(bǔ)rgs里的元素作為values的元素 self.count = {}.fromkeys(range(len(self.values)),0) def __len__(self): return len(self.values) def __getitem__(self,key): self.count[key] += 1; return self.values[key] c = CountList(1,3,5,7,9,11) print(c[1]) print(c[1]+c[2]) print(c.count) # output: # 3 # 8 # {0: 0, 1: 2, 2: 1, 3: 0, 4: 0, 5: 0}
該類中的count是記錄對(duì)應(yīng)元素被訪問的次數(shù),其他兩個(gè)也差不多,不再舉例了
迭代器,就是提供了迭代方法的容器,而所謂的迭代方法,就是下面這兩個(gè)__iter__
和__next__
可迭代,就是提供了__iter__
方法的容器,我們之前講的字符串,列表,元組,字典,集合都是可迭代的,但他們不是迭代器,可以使用Python的內(nèi)置函數(shù)iter(iterable)
來獲取他們相應(yīng)的迭代器,而迭代器使用next(iterator)
可以獲取下一個(gè)元素,而這兩個(gè)方法其實(shí)就是調(diào)用了迭代器的__iter__
和__next__
__iter__(self)
:定義獲取迭代器時(shí)的行為
__next__(self)
:定義獲取迭代器對(duì)應(yīng)的下一個(gè)元素時(shí)的行為
class Fb: def __init__(self,n = 20): self.a = 0 self.b = 1 self.n = n def __iter__(self): return self def __next__(self): t = self.a self.a = self.b self.b = t + self.b if(self.a <= self.n): return self.a else: raise StopIteration f = Fb() for i in f: print(i,end=' ') # output:1 1 2 3 5 8 13
其中 raise 是返回一個(gè)異常,上面的程序等價(jià)于下面這個(gè)
class Fb: def __init__(self,n = 20): self.a = 0 self.b = 1 self.n = n def __iter__(self): return self def __next__(self): t = self.a self.a = self.b self.b = t + self.b if(self.a <= self.n): return self.a else: raise StopIteration f = Fb() it = iter(f) while True: try: i = next(it) print(i, end=' ') except StopIteration: break;
這樣我們就很清楚Python中for循環(huán)的原理了,先通過iter來獲取迭代器對(duì)象,然后不斷調(diào)用next來獲取下一個(gè)元素賦值給i,直到遇到StopIteration異常
關(guān)于“Python常用的魔法方法是什么”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。