詳解Python常用的魔法方法
一、python魔法方法
Python的魔法方法會(huì)在特定的情況下自動(dòng)調(diào)用,且他們的方法名通常被雙下劃線包裹,之前我們學(xué)習(xí)的構(gòu)造函數(shù)和析構(gòu)函數(shù)就屬于魔法方法
二、運(yùn)算符重載
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常用的魔法方法的文章就介紹到這了,更多相關(guān)python魔法方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python機(jī)器學(xué)習(xí)利用隨機(jī)森林對(duì)特征重要性計(jì)算評(píng)估
本文是對(duì)隨機(jī)森林如何用在特征選擇上做一個(gè)簡單的介紹。隨機(jī)森林非常簡單,易于實(shí)現(xiàn),計(jì)算開銷也很小,更令人驚奇的是它在分類和回歸上表現(xiàn)出了十分驚人的性能2021-10-10
Python 中的 dataclass使用場(chǎng)景與代碼示例詳解
在Python中,dataclass是一個(gè)裝飾器,用于簡化類的定義,自動(dòng)生成初始化、比較等方法,適用于需要存儲(chǔ)數(shù)據(jù)的場(chǎng)景,通過示例展示了dataclass的基本用法,感興趣的朋友跟隨小編一起看看吧2024-09-09
Python web框架fastapi中間件的使用及CORS跨域問題
fastapi "中間件"是一個(gè)函數(shù),它在每個(gè)請(qǐng)求被特定的路徑操作處理之前,以及在每個(gè)響應(yīng)之后工作,它接收你的應(yīng)用程序的每一個(gè)請(qǐng)求,下面通過本文給大家介紹Python web框架fastapi中間件的使用及CORS跨域問題,感興趣的朋友一起看看吧2024-03-03
OpenCV清除小面積連通域的實(shí)現(xiàn)方法
本文主要介紹了OpenCV清除小面積連通域的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
Python辦公自動(dòng)化之JSOM數(shù)據(jù)處理與SQL Server數(shù)據(jù)庫操作
這篇文章主要為大家詳細(xì)介紹了Python辦公自動(dòng)化中JSOM數(shù)據(jù)處理與SQL Server數(shù)據(jù)庫操作的相關(guān)知識(shí),文中的示例代碼簡潔易懂,有需要的小伙伴可以參考下2024-01-01
Pyqt清空某一個(gè)QTreeewidgetItem下的所有分支方法
今天小編就為大家分享一篇Pyqt清空某一個(gè)QTreeewidgetItem下的所有分支方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-06-06
Python中使用Opencv開發(fā)停車位計(jì)數(shù)器功能
這篇文章主要介紹了Python中使用Opencv開發(fā)停車位計(jì)數(shù)器,本教程最好的一點(diǎn)就是我們將使用基本的圖像處理技術(shù)來解決這個(gè)問題,沒有使用機(jī)器學(xué)習(xí)、深度學(xué)習(xí)進(jìn)行訓(xùn)練來識(shí)別,感興趣的朋友跟隨小編一起看看吧2022-04-04

