在現代編程世界中,面向物件編程(OOP)語言在改變軟體開發中的設計和實作模式方面發揮了進化作用,作為OOP家族的重要成員,Python在過去10年左右逐漸流行起來,與其他OOP語言一樣,Python圍繞大量不同的物件操作其資料,包括模塊、類和函式,
如果您有任何OOP語言的編程經驗,您應該知道所有物件都有其內部特征資料,稱為欄位、屬性或屬性,在Python中,這些物件系結的特征資料通常稱為屬性,在本文中,我將特別在自定義類的背景關系中討論它們,

?
1. 類屬性
為了更好地管理專案中的資料,我們經常需要創建自定義類,在Python中,類也是物件,這意味著它們可以有自己的屬性,讓我們看一個例子,

?
如上所示,我們宣告了一個名為Dog的類,因為所有的狗都屬于犬類屬和犬科家族,所以我們創建了兩個類屬性,分別命名為屬和科來存盤這兩條資訊,如您所見,我們可以直接使用類來訪問這些屬性,我們可以使用函式dir來顯示狗的屬性串列,其中包括家族和屬,
這些定義為類級別的屬性稱為類屬性,類可以直接檢索它們,但是,與其他OOP語言不同,Python中的實體物件也可以直接訪問這些類屬性,如下面的代碼片段所示,

?
2. 實體屬性
通過自定義類,我們還可以為實體物件設定屬性,這些屬性稱為實體屬性,這意味著它們是特定于實體的資料,讓我們繼續狗類,

?
在上面的代碼中,我們定義了__init__函式,它將作為創建一個新的Dog實體的構造方法,第一個引數self參考了我們正在創建的實體,在實體化期間(即創建新實體),我們將為新實體物件分配品種和名稱資訊,這些屬性將成為實體特征的一部分,如下所示,

?
需要注意的一點是,我們可以為具有與class屬性相同的屬性的實體賦值,在這種情況下,當您檢索實體的這個屬性時,將不會檢索class屬性,換句話說,當您使用一個實體物件來檢索class屬性時,Python將首先檢查實體本身是否有一個用相同名稱設定的屬性,如果沒有,Python將使用class屬性作為回退,此外,設定一個實體的屬性不會影響同名類的屬性,讓我們在下面的代碼片段中看看這些特征,

?
3. 函式作為屬性
在Python中,一切都是物件,前面我已經提到類是物件,此外,函式是Python物件,在類中,我們可以定義函式,通常稱為方法,根據使用這些函式的方式,我們可以將它們進一步分類為類方法、靜態方法和實體方法,在這里,理解這些差異并不是必須的,
盡管某些OOP語言將屬性(或屬性)和函式視為不同的物體,但Python將這些方法(函式)視為類的屬性——與我們前面定義的類屬性沒有太大區別,讓我們用上面提到的三種方法來更新Dog類:類方法、靜態方法和實體方法,如下所示,

?
對于更新后的類,我們可以使用函式dir檢查類的屬性串列,如下所示,類方法和靜態方法都包含在串列中,

?
然而,有一件事可能會讓一些人感到驚訝,那就是該串列中包含了實體方法bark,我們知道,實體方法是那些由實體物件呼叫的函式,因此有些人可能認為這些實體方法應該系結到所有單獨的實體,然而,在Python中卻不是這樣,在解釋實體方法如何作業之前,讓我們先看看下面的代碼,

?
如上所示,我們首先創建了Dog類的一個實體,與其他OOP語言一樣,實體物件可以直接呼叫實體方法bark,然而,Python與其他語言的不同之處在于,實體方法的呼叫是通過類來操作的,通過傳遞實體作為引數來呼叫定義的函式(即,dog .bark(dog)),換句話說,instance.inst_method()在本質上與Python中的Class.inst_method(instance)相同,
之所以可以這樣做,是因為Dog類“擁有”實體方法,這是一種節省記憶體的機制,因為Python不需要為每個實體物件創建單獨的函式副本,相反,當一個實體呼叫一個實體方法時,Python將呼叫委托給類,該類將通過傳遞實體呼叫相應的函式(它將被設定為已定義函式中的self引數),
4. 私有屬性
如果您有OOP的經驗,就不應該不熟悉訪問修飾符的存在,比如public、private和protected,這些修飾符限制了可以訪問修改的屬性和函式的范圍,然而,您很少在Python中聽到這樣的討論,實際上,如果借用OOP中的術語,所有Python屬性都是公共的,如上所示,在類和實體可以訪問的地方,類和實體屬性都可以自由訪問,因此,嚴格地說,Python中沒有真正的私有或受保護的屬性(后面將討論),我們只是類比地使用這些術語,以便來自其他OOP背景的程式員更容易理解相關的編碼約定(是的,只是一種約定,沒有作為真正的訪問控制加以加強),
讓我們首先討論一下如何在Python中定義“私有”屬性,慣例是用兩個前導下劃線命名這些屬性,并且不超過一個后引下劃線,考慮下面更新過的Dog類的示例—為了簡單起見,我們省略了前面定義的其他屬性,

?
在上面的更新之后,Dog實體將擁有一個名為tag的私有屬性,正如其名稱所示,實體物件仍然可以像以前一樣訪問它的其他屬性(例如,名稱),然而,實體不能訪問私有屬性剩余的標記,這可能是我們所期望的,實際上,這種對訪問這些屬性的限制正是它們被稱為“私有”屬性的原因,但它是怎么發生的,在引擎蓋下?畢竟,我前面提到過,所有Python屬性在默認情況下都是公共的,下面將向您展示Python如何實作“私有”屬性,

?
__dict__特殊方法(也稱為dunder方法,在名稱前后都有雙下劃線)能夠顯示物件的字典表示,具體來說,字典中的鍵-值對是物件的屬性及其值,正如我們所看到的,除了bread和name屬性之外,還有一個名為_dog__tag標記的屬性,這個屬性正是私有屬性__tag通過一個稱為mangling的程序與物件關聯的方式,
具體來說,mangling或name mangling是使用_ClassName作為私有屬性的前綴,這樣我們就人為地創建了對這些“私有”屬性的訪問限制,但是,如果我們確實想檢索任何私有屬性,我們仍然可以使用被破壞的名稱訪問它,就像我們在代碼片段中使用_dog__標記所做的那樣,
5. 受保護的屬性
在上一節中,我們討論了私有屬性,但是受保護的屬性呢?Python中與受保護屬性對應的屬性名稱只有一個下劃線,不像雙下劃線會導致混亂,單下劃線前綴不會改變Python解釋器處理這些屬性的方式——它只是Python編程世界的一個慣例,表示他們(例如,編碼器)不希望你訪問這些屬性,但是,如果你堅持要訪問它們,你仍然可以這樣做,讓我們看看下面的代碼,

?
我們通過創建一個名為_nickname的實體屬性來更新類Dog,正如其名稱使用下劃線前綴所表明的那樣,按照約定,它被認為是一個“受保護”的屬性,我們仍然可以將這些受保護的屬性作為其他“公共”屬性來訪問,但是一些ide或Python編輯器不會為這些非公共屬性提供提示(例如,自動完成提示),有關這些使用Jupyter筆記本的例子,請參見螢屏截圖,

?
如果我們使用模塊而不是類,就像我們在這里所做的那樣,當我們使用from _module import *匯入模塊時,帶有下劃線前綴的名稱將不會被匯入,從而提供了一種機制來限制對這些“受保護的”屬性的訪問,
此文轉載文,著作權歸作者所有,如有侵權聯系小編洗掉!
原文地址:https://www.tuicool.com/articles/VzAvmum
需要源代碼或者想了解更多的(點擊這里查看)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/142365.html
標籤:其他
