python中属于私有属性的是_Python中的实例属性和私有属性
相關知識點
實例屬性
實例屬性和類屬性的區(qū)別在于實例屬性定義在類的__init__()魔法方法中,而類屬性定義在類下:
1 classC:2 b = 1 #類屬性
3
4 def __init__(self):5 self.x = None #實例屬性
對于類屬性這里不做說明,主要描述實例屬性,
實例屬性生效的方式要先知道的一點是Python中實例化一個類,類的魔法方法__init__()會被自動調(diào)用,
所以對于類對象C來說,是不存在實例屬性的,在C類對象被實例化的時候,實例屬性x才會被創(chuàng)建:
1 classC:2 b = 1
3
4 def __init__(self):5 self.x =None6
7 print(C.b)8 print(C.x)
上述代碼中行7print會被執(zhí)行,因為C.b是類屬性,類屬性可以被使用,
但是行7的print會報錯AttributeError: type object 'C' has no attribute 'x' ,就是因為C類對象沒有x屬性,因為__init__()只有在類對象被實例化的時候,才會被執(zhí)行,
當C類對象被實例化,訪問實例對象的x,就不會報錯,這就是實例屬性(只有實例才能訪問):
1 classC:2 b = 1
3
4 def __init__(self):5 self.x =None6
7
8 a = C() #實例化C
9 print(a.x) #訪問a實例的x
私有屬性
有些時候我們定義一個類,并且構造了實例屬性,并且在內(nèi)部方法中使用了這個屬性,通常不希望這個屬性會被外部(類方法外)更改,否則就會出現(xiàn)一些不可預料的問題,例如:
1 classC:2
3 def __init__(self):4 self.doc = '這個例子是我在2020_06_11寫的'
5
6 defprintf(self):7 print(f'{self.doc}')8
9 a = C() #把C實例化,命名為a
10 a.doc = '我想給a實例增加一個doc屬性' #本來的想法是給a實例增加一個doc屬性,但是卻不知道C實例在內(nèi)部也定義了doc實例屬性,并且在類方法中需要用到這個屬性
11 a.printf()
這段代碼的輸出:我想給a實例增加一個doc屬性
上述的例子中只是改了一個doc,在實際編碼過程中,這個屬性很可能是一個關鍵數(shù)據(jù),類方法強依賴于這個屬性,如果未經(jīng)校驗就讓外部直接對這個屬性進行修改,就會造成不可預估的后果,很可能需要花很長時間來定位問題。
綜上所述在一些場景下,我們需要把類屬性定義為私有屬性,這樣我們在外部就無法對實例的私有屬性做修改,而在類內(nèi)部,卻依然可以對私有屬性做修改和處理,
下面我們舉一個數(shù)字類的加法例子:
1 classNum:2
3 def __init__(self):4 self.__x = 1
5 self.__y = 2
6
7 defprintf(self):8 print(f'{self.__x}加{self.__y}的和是:{self.__x+self.__y}')9
10 a = Num() #把C實例化,命名為a
11 a.printf()
這段代碼輸出是:1加2的和是:3
這個例子中我們就把實例屬性x和y前面加上了雙下劃線__,告訴Python解釋器這個是私有屬性,不能被更改,
這個時候如果我們企圖在類的外部修改私有屬性,實際上實例方法printf中調(diào)用的實例對象__x,__y就不會受到影響:
1 classNum:2
3 def __init__(self):4 self.__x = 1
5 self.__y = 2
6
7 defprintf(self):8 print(f'{self.__x}加{self.__y}的和是:{self.__x+self.__y}')9
10 a = Num() #把C實例化,命名為a
11 a.__x = 5
12 a.__y = 5
13 a.printf()
這里的返回仍然是:1加2的和是:3
因為我們把x和y定義成了私有屬性,就這么簡單
總結
Python中實例實例屬性在類被實例化的時候才會被創(chuàng)建;
以雙下劃線__開頭的實例屬性被稱為私有屬性,私有屬性不會被類外部修改。
拓展知識
實際上在Python中并沒有絕對的私有和共有屬性,
我們使用雙下劃線的方式來定義一個私有實例屬性,也僅僅是提醒上層:這是一個私有變量,請不要擅自修改,否則可能出現(xiàn)不可預知的錯誤!
所以為什么我們可以通過這種方式來限制上層讓上層的修改無效呢?
我們可以用實例對象的魔法方法__dir__()來查看這個實例擁有的屬性:
1 classNum:2
3 def __init__(self):4 self.__num = 1
5
6
7 a = Num() #把C實例化,命名為a
8 print(a.__dir__())
輸出:
['_Num__num', '__module__', '__init__', '__dict__', '__weakref__', '__doc__', '__repr__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__new__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']
其他的可以不看,a實例下會有一個'_Num__num' 屬性,這個屬性就是我們在初始化函數(shù)__init__()中定義的__num,
到這里就已經(jīng)很清楚了,Python解釋器,把雙下劃線開頭的__num認為是私有屬性,把私有屬性重命名成了 _類名 + 私有屬性名,
所以我們在上層可以對實例對象的__num重新賦值,但是并不會影響類內(nèi)部使用的self.__num,這只是因為調(diào)用的self.__num和重新定義的a.__name并不是同一個屬性,
我們可以通過這種方式來驗證我們的想法:
1 classNum:2
3 def __init__(self):4 self.__num = 1
5
6 defprintf(self):7 print(self.__num)8
9 a = Num() #把C實例化,命名為a
10 print('下面調(diào)用類方法printf,輸出類中的__name')11 a.printf()12 print('接下來在外部修改__name的值,再輸出看看外部調(diào)用的__name的值')13 a.__num = 3
14 print(a.__num)15 print('再看看我們這個實例的屬性和方法')16 print(a.__dir__())
這里的輸出:
下面調(diào)用類方法printf,輸出類中的__name1
接下來在外部修改__name的值,再輸出看看外部調(diào)用的__name的值3
再看看我們這個實例的屬性和方法['_Num__num', '__num', '__module__', '__init__', 'printf', '__dict__', '__weakref__', '__doc__', '__repr__', '__hash__', '__str__', '__getattribute__', '__setattr__', '__delattr__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__new__', '__reduce_ex__', '__reduce__', '__subclasshook__', '__init_subclass__', '__format__', '__sizeof__', '__dir__', '__class__']
現(xiàn)在實錘了,類中的self.__name實際上是_Num__num,我們外部定義的a.__name實際上就是__name
所以如果我們就是想要修改私有屬性,我們就可以這樣做:
1 classNum:2
3 def __init__(self):4 self.__num = 1
5
6 defprintf(self):7 print(self.__num)8
9 a = Num() #把C實例化,命名為a
10 print('下面調(diào)用類方法printf,輸出類中的__name')11 a.printf()12 print('接下來在外部修改_Num__num的值')13 a._Num__num = 3
14 print('下面直接在外部訪問私有屬性')15 print(a._Num__num)16 print('下面調(diào)用類方法printf,輸出類中的__name')17 a.printf()
輸出:
下面調(diào)用類方法printf,輸出類中的__name
1
接下來在外部修改_Num__num的值
下面直接在外部訪問私有屬性
3
下面調(diào)用類方法printf,輸出類中的__name
3
總結
以上是生活随笔為你收集整理的python中属于私有属性的是_Python中的实例属性和私有属性的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安卓沙箱软件(安卓沙箱)
- 下一篇: python中mean的用法_Pytho