python面向對象第二周魔術方法詳解

魔法方法及其使用
__開頭和結束的方法,定義外部沒有辦法直接調用,但會有影響使用
運算符號的魔法方法, + ,-,*,/,%,//,**, __add__,__sub__,__mul__,__truediv__,__mod__,__floordiv__,__pow__,
__divmod__(?),
系統內部對于數值型,字符串型,容器內型都定義了其中部分或者全部的運算符使用要求和辦法,
我們在類中定義這些魔法方法,可以使得它們按照需要對對象類型進行運算符運算, 仍需要滿足一些基本的概念
比如加減乘除都是在兩個對象而言的,所以形參數量要為二 ,且其中一個為self(類自身的對象)其他大部分的運算符魔法方法對于參數數量和類型也有類似要求,
其他變種運算符 +=,-=,*=,/=,%=,//=,**= ,它們的魔法方法寫法就是相應的名稱前加一個i,它們對于形參數和類型也與前面的類似
判斷運算符 <,<=,==,>,>=,!=
和運算符號的一樣,他么的返,定義一般要求兩個參數,且其中一個為self(類自身的對象),它們不一定要求返回布爾型的值,可以沒有或者返回其他類型的值
在使用這些運算符對系統數據類型使用這些符號時不會有覆蓋,或者不能使用的問題,因為他們內部的類中有魔法方法定義使用這些符號的使用規則,即使我們在自定義的類中對基本數據類型時使用運算符,依然能夠準確表達含義

容器相關方法:__len__,__iter__,__contains__,__getitem__,__setitem__,__missing__
獲取長度,迭代器, in運算符,索引訪問,索引設置,其它
容器相關方法,在基本數據類型中的容器類型,list,tuple,set,dict中有實現其中大部分或全部方法,
對他們調用 len( ),可以使用是因為實現了__len__的魔法方法,在類中可以定義它,使得我們也可以在外部調用該方法,這個方法要求只有一個形參,且為類的對象,要有返回值且為整型,使用 len(對象)會調用這個方法
當迭代一個對象(使用for in 遍歷)時會調用__iter__的方法,獲取該方法返回的迭代器,for in 遍歷的實質是遍歷這個迭代器,所以這個對象可以被成為可迭代對象,任何數據類型如果實現__iter_就是一個可迭代類型. 實現__iter__
方法要求傳入一個參數,為self(類自身的對象)返回一個迭代器 (iter( )函數,yield from iterable都可以返回一個迭代器)
__contains__(self,item) 使用判斷語句 in 的時候調用的方法 如果使用 ” item in 對象 ” 就會調用這個方法
如果沒有定義該方法依然可以使用,in 語句 自是他會自動調用 對象的 __iter__方法獲取它的迭代器 相當于對對迭代器使用 in 語句. __contains__ 方法要求有返回值且為布爾型,若不為布爾型根據返回值是否為空類型返回True 或 False
索引訪問 對象[ ] ,調用__getitem__方法 __getitem__(self,item) item為索引
形參只能為兩個(如果不定義兩個調用時將會出現無法處理的錯誤),item為傳入中括號中的值,但系統對這個值要求非常松,可以為任意類型
使用索引賦值(賦值即定義) 對象[ ] =值 ,調用__setitem__方法 __setitem__(self,key,value) key為中括號中的值,value為等號右邊的值
其他 __missing__, 當調用了__getitem__()方法,而key不存在就會調用這個方法(只能被動的調用)

總結:魔法方法,在使用中不像普通方法一樣調用方法名就能夠使用,他是系統中設置好的,我們在類中能夠對它重寫,對于運算符,重寫的要求很簡單,傳入兩個參數對于函數內部實現沒有要求. 對于函數體實現沒有要求.
對于容器類型的相關方法,它的參數可能要求很低,但使用中可能會出錯,很多對于返回值也有要求,要求有且返回
指定類型. 實際在一個容器中,對于函數的實現它的要求其實會更高,例如它要實現索引設置和獲取,要求把設置的內容保存,獲取時從內部獲取.基本數據類型中除了容器類型,還有其他類型實現了其中的部分方法

對象的打印,正常使用print函數打印一個對象會獲得<__main__.A object at 0x00000272662DF6A0>這樣的結果
__repr__ , __str__ 兩個方法可以作為對象的顯示方法
在print 和 format 函數中如果要打印對象會優先調用__str__方法, 如果打印一個包裝了對象的基本數據類型的時候,會先執行打印基本數據類型的方法,其中的對象只會調用對象的__repr__方法

可調用對象__call__ 如果一個對象可以像函數一樣的訪問,因為實現了這個方法,對參數,返回值沒有要求
__enter__,__exit__,使用條件苛刻,上下文管理(with語句)時才會執行,這兩個方法都是被動調用的

@functools.total_ordering裝飾器
類中實現包含等于,包含大于小于之一的兩個方法就會實現六個方法

反射相關魔術方法:
首先看看反射相關的內建函數 getattr(對象,name[,default]) 通過name(字符串類型) 獲取對象中叫作name的屬性,沒有就返回default,沒設置會報錯
setattr(對象,name,value) 設置對象的屬性和值,有就覆蓋,沒有就新增
hasattr(對象,name) 判斷對象是否有這個名字的屬性
__getattr__(self,item) 外部對對象使用 對象.name 訪問時,訪問字典不能得到,最后執行的方法
__setattr__(self,key,value) 需要通過 對象.key = value 來為對象添加屬性的時候自動調用,并攔截添加或覆蓋操作,需要在其中重寫這個方法,或用屬性字典手動添加
__delattr__ 使用del語句刪除對象時調用,并攔截刪除
__getattribute__ 獲取對象屬性時會優先執行,如果要能正常執行獲得真實結果返回
return object.__getattribute__(self.item)

總結:魔術方法,如果定義只要滿足調用的條件就會自動的觸發,暫時沒有出現可以自行設置觸發條件的魔術方法.
方法中,系統實現的部分直接或間接指示了參數含義,如果不順著系統意思,在實際調用中可能會出現意想不到的錯誤. 類中的方法在實現時如果滿足類中定義的魔術方法觸發條件,將會觸發. 魔術方法除了有方便應用和表達含義的符號,還有的實現特殊功能的,比如上下文管理 ,__call__外部訪問,這些方法極大地擴展了類的功能.
顯示和反射有關的魔術方法都屬于工程,工具類型的魔術方法

描述器和它的三個魔術方法
:__get__ (self,instance,owner), __set__(self,instance,value) , __delete__(self, instance)
__get__ 外部的類的屬性(類變量)訪問就會調用,這個方法, 對象如果通過類變量訪問,也會調用,它的返回值為訪問到的值
__set__ 外部的類中設置對象屬性值會調用,并攔截對象屬性的設置

一個類中如果有這幾個方法之一它就是一個描述器
如果一個類中的類屬性(類變量)引入了一個描述器對象, 修飾器就能夠作用于這個類. 滿足條件的情況就會調用描述器中的方法. 分為很多情況
1,只有__get__, 描述器被類訪問,會調用描述方法,且類變量的值為它的返回值,如果它對象通過類變量訪問到修飾器,也會執行相同的操作
2,只有__set__, 在類的內部或外部,給類的對象添加或修改與描述器變量名相同的屬性, 會觸發描述器方法,它的返回值沒有意義
3,有__del__, 在外部使用del 作用對象訪問的,與描述器變量名想同的屬性時,會調用 ,如果是用類訪問到的不會調用

對于一個描述器有多個這樣的方法,如果滿足各自的條件就會觸發訪問,其中只有__get__為 非數據描述器
有__get__和__set__成為為數據描述器. 描述器的使用大概分為三塊:1,定義描述器2,生成被描述的類并加載描述器3,外部調用被描述類的屬性觸發描述方法,后兩種它可以起到對特定屬性的監視作用.
數據描述器功能比非數據描述器強大

應用實例定義一個靜態方法裝飾器
class StaticMtd:
def __init__(self,fn):
self.fn = fn
def __get__(self, instance, owner):
print(‘get’)
return self.fn
def __set__(self, instance, value):
print(self,instance,value)
print(‘set’)
class A:
@StaticMtd # add = StaticMtd(add) 相當與引入了一個描述器
def add(x,y):
print(x,y)
A.add(4,5) #使用類訪問觸發描述器的方法
a =A()
a.add = 3 #使用對象添加與描述器變量名相同屬性,觸發set方法

本文來自投稿,不代表Linux運維部落立場,如若轉載,請注明出處:http://www.www58058.com/88806

(1)
daishitongdaishitong
上一篇 2017-11-21
下一篇 2017-11-23

相關推薦

  • inotify+rsync同步方案(ubuntu,適用其他發行版)

    系統:Ubuntu 16.04.1  工具:rsync 3.1.1 、inotify -tools 3.14      作者:jevtse    本文除了軟件安裝部分,其他內容同樣適用其他linux系統;同步目標主機:172.16.250.…

    2017-03-05
  • 第五周

    1、簡述rpm與yum命令的常見選項,并舉例
    2、自建yum倉庫,分別為網絡源和本地源
    3、簡述at和crontab命令,制定 每周三凌晨三、五點10分執行某個腳本,輸出當前時間,時間格式為 2017-12-28 10:00:00
    4、簡述sed常用操作命令,并舉例

    Linux干貨 2017-12-30
  • 新的篇章

    第一天,linux,努力,奮斗!

    Linux干貨 2017-07-11
  • 文件的從屬權限和特殊權限

    基礎權限   rwx     經過今天的洗禮,了解了文件的權限位(rwx),而權限對于目錄和文件有著不同的意義     使用ls -l 命令后可以看到     -rw-r–r–. 1 root root 1…

    Linux干貨 2016-08-04
  • N23_第五周

    1.顯示/boot/grub/grub.conf中以至少一個空白字符開頭的行 egrep “^[[:space:]]{1,}” /boot/grub/grub.conf 2.顯示/etc/rc.d/rc.sysinit文件中以#開頭,后面跟至少一個空白字符,而后又有至少一個非空白字符的行 egrep “^#[[:space:]]{1,}.*[^[:space…

    Linux干貨 2017-02-27
  • Linux的自動化安裝實現

    在介紹自動化安裝系統之前讓我們來回顧一下系統的啟動流程,系統的啟動大概分為一下幾個步驟:加電自檢 boot sequence(mbr)— boot loader –>kernel(initramfs)—>rootfs  /sbin/init大概就是這么幾個過程了,接下來來介紹系統的安裝,安裝系統雖然看起來簡單,普…

    系統運維 2016-09-19
欧美性久久久久