日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

__getattr__在python2.x与python3.x中的区别及其对属性截取与代理类的影响

發(fā)布時間:2024/9/5 python 54 豆豆
生活随笔 收集整理的這篇文章主要介紹了 __getattr__在python2.x与python3.x中的区别及其对属性截取与代理类的影响 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

python2.x中的新類型類(New-style class)與python3.x的類一致,均繼承object類,而不繼承object的類稱為經(jīng)典類(classic class),而對于這兩種類,一般實例屬性截取函數(shù)(generic instance attribute interception methods)的行為有所不同,其在3.x和2.x的新類型類中,不再被__x__操作符重載函數(shù)名(operator overloading name)的內(nèi)建操作調(diào)用,對于該操作符重載函數(shù)名的搜索直接在類中搜索,而非實例中,而對于顯式名的屬性獲取,包括__x__名,仍然要路經(jīng)__getattr__,因此這是對于內(nèi)建操作行為的主要影響,這種影響進(jìn)而又影響到屬性截取以及代理類。比如一個類定義了__getitem__索引重載函數(shù),x是該類的一個實例,對于經(jīng)典類來說,x[I]與x.__getitem__(I)等價,而對于新類型類來說,x[I]不再被__getattr__獲取,而顯式x.__getitem__仍然可以被獲取。

1.對屬性截取的影響:

首先看__getattr__在經(jīng)典類與新類型類中表現(xiàn)的差異。

(1)在新類型類中(下列代碼在3.x中實現(xiàn)):

>>> class c:
?data='spam'
?def __getattr__(self,name):
??print('getattr->'+name)
??return getattr(self.data,name)
>>> x=c()
>>> x[0]
Traceback (most recent call last):
? File "<pyshell#7>", line 1, in <module>
??? x[0]
TypeError: 'c' object does not support indexing

構(gòu)造了一個名為c的類,類長__getattr__方法可截取實例屬性,然后打印截取到的屬性名,最后返回實例對象的data對象的name方法結(jié)果。而對于x[0]內(nèi)建操作表達(dá)式,則拋出了異常,該異常為c對象不支持索引,因此可以看出x[0]是直接在類中進(jìn)行搜索,而跳過了實例屬性截取函數(shù)__getattr__。

>>> getattr->__getitem__ x.__getitem__(0) getattr->__getitem__ 's'

而x.__getitem__(0)方法可以被__getattr__獲取,類似的,對于其他內(nèi)建操作,比如,x+'eggs',與x.__add__('eggs'),也有相同的反應(yīng)。

>>> getattr->__add__ x.__add__('eggs') getattr->__add__ 'spameggs' >>> x+'eggs' Traceback (most recent call last):File "<pyshell#12>", line 1, in <module>x+'eggs' TypeError: unsupported operand type(s) for +: 'c' and 'str' >>> type(x).__getitem__(x,0)
Traceback (most recent call last):
? File "<pyshell#18>", line 1, in <module>
??? type(x).__getitem__(x,0)
AttributeError: type object 'c' has no attribute '__getitem__'

當(dāng)用x的類(即c)調(diào)用__getitem__,可以預(yù)想到的,拋出AttributeError,因為c并沒有__getitem__方法。

(2)以上代碼在經(jīng)典類中(在2.x中實現(xiàn)):

>>> class c:data='spam'def __getattr__(self,name):print('getattr->'+name)return getattr(self.data,name)File "<pyshell#0>", line 2class c:^ IndentationError: unexpected indent >>> class c:data='spam'def __getattr__(self,name):print('getattr->'+name)return getattr(self.data,name)>>> x=c() >>> x[0] getattr->__getitem__ 's' >>> getattr->__getitem__ x.__getitem__(0) getattr->__getitem__ 's' >>> getattr->__add__ x.__add__('eggs') getattr->__add__ 'spameggs' >>> x+'eggs' getattr->__coerce__ getattr->__add__ 'spameggs'

可以看到,在經(jīng)典類型中,測試全部通過。

>>> type(x).__getitem__(0)Traceback (most recent call last):File "<pyshell#8>", line 1, in <module>type(x).__getitem__(0) TypeError: descriptor '__getitem__' requires a 'instance' object but received a 'int'

但是,嘗試用c類調(diào)用__getitem__,卻拋出異常,主要是描述符(descriptor)的參數(shù)錯誤造成的,關(guān)于描述符的總結(jié),將在后面的文章中專門整理。

2.對代理類的影響

實際上,在屬性截取中,已經(jīng)提到,在新類型類中,當(dāng)直接用隱式的內(nèi)建操作表達(dá)式,如x[i],x+等,拋出AttributError的異常,因為這種情況下,是直接從類開始搜索的,而c類中沒有,所以才拋出了異常,那該怎么辦呢?一個很自然的辦法就是在類中,對要代理的隱式內(nèi)建操作表達(dá)式進(jìn)行重新定義,所以類就具備了要代理操作屬性。

>>> class c:data='spam'def __getattr__(self,name):print('getattr->'+name)return getattr(self.data,name)def __getitem__(self,i):print('getitem:'+str(i))return self.data[i]def __add__(self,other):print('add->'+other)return getattr(self.data,'__add__')(other)

上述代碼在3.x中實現(xiàn),通過對類c重新定義__getitem__,__add__重新定義實現(xiàn)了代理索引和加操作。

>>> x=c() >>> x.upper() getattr->upper 'SPAM'

可以看到__getattr__截取了一般方法upper()。

>>> x[0] getitem:0 's' >>> x.__getitem__(0) getitem:0 's' >>> x+'eggs' add->eggs 'spameggs' >>> x.__add__('eggs') add->eggs 'spameggs'

可以看到,代理成功。

(3)進(jìn)一步的理解

事實上,子類繼承基類(超類)的屬性或者方法若在子類中沒有重載,而子類實例若調(diào)用該屬性,將不被__getattr__攔截,直接調(diào)用基類的屬性。如下代碼:

>>> class c:def test(self):print('test from c')>>> class d(c):def __getattr__(self,attr):print('getattr'+attr)>>> x=d() >>> x.test() test from c

?

轉(zhuǎn)載于:https://www.cnblogs.com/johnyang/p/10461887.html

總結(jié)

以上是生活随笔為你收集整理的__getattr__在python2.x与python3.x中的区别及其对属性截取与代理类的影响的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。