您好,登錄后才能下訂單哦!
python中用雙下劃線開頭的方式把屬性隱藏起來(設置成私有的)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: vita
#其實這僅僅這是一種變形操作
#類中所有雙下劃線開頭的名稱如__x都會自動變形成:_類名__x的形式:
class A:
__N=0 #類的數據屬性就應該是共享的,但是語法上是可以把類的數據屬性設置成私有的如__N,會變形為_A__N
def __init__(self):
self.__X=10 #類定義時就變形為self._A__X
def __foo(self): #類定義時就變形為_A__foo
print('from A')
def bar(self):
self.__foo() #只有在類內部才可以通過__foo的形式訪問到.
a = A()
print("a.__dict__",a.__dict__)
#定義后的賦值操作,不會變形為_類名__N
a.__Y=1
print("a.__dict__",a.__dict__)
print("a._A__N:",a._A__N)
print("A._A__N:",A._A__N)
#A._A__N是可以訪問到的,即這種操作并不是嚴格意義上的限制外部訪問,僅僅只是一種語法意義上的變形
E:\PythonProject\python-test\venvP3\Scripts\python.exe E:/PythonProject/python-test/BasicGrammer/test.py
a.__dict__ {'_A__X': 10}
a.__dict__ {'_A__X': 10, '__Y': 1}
a._A__N: 0
A._A__N: 0
Process finished with exit code 0
這種自動變形的特點:
1.類中定義的__x只能在內部使用,如self.__x,引用的就是變形的效果。
2.這種變形其實是針對外部的變形,在外部是無法通過__x這個名字訪問到的。
3.在子類定義的__x不會覆蓋在父類定義的__x,
因為子類中變形成了:_子類名__x,
而父類中變形成了:_父類名__x,即雙下劃線開頭的屬性在繼承給子類時,子類時無法覆蓋的。
這種變形要注意的問題:
"1.這種機制并沒有真正意義上限制我們從外部直接訪問屬性,知道了類名和屬性名還可以拼出名字:_類名__屬性,然后就可以訪問了,如a._A__N或A._A__N"
"2.變形的過程只在類定義時發生一次,在定義后的賦值操作,不會發生變形"
print("a.__dict__",a.__dict__)
#定義后的賦值操作,不會變形為_類名__N
a.__Y=1
print("a.__dict__",a.__dict__)
a.__dict__ {'_A__X': 10}
a.__dict__ {'_A__X': 10, '__Y': 1}#這里依舊是__Y,并沒變形為_A__Y
"3.在繼承中,父類如果不想讓子類覆蓋自己的方法,可以把方法定義為私有的"
#正常情況
>>> class A:
... def fa(self):
... print('from A')
... def test(self):
... self.fa() #這里先到對象自身的類中找,找不到再到A類中找
...
>>> class B(A):
... def fa(self):
... print('from B')
...
>>> b=B()
>>> b.test()
from B
#把fa定義成私有的,即__fa
>>> class A:
... def __fa(self): #在定義時就變形為_A__fa
... print('from A')
... def test(self):
... self.__fa() #在定義階段,變形為self._A__fa,所以只會與自己所在的類為準
...
>>> class B(A):
... def __fa(self): #在定義階段,變形為self._B__fa
... print('from B')
...
>>> b=B()
>>> b.test() #注意這里調用的self.__fa()為類A中的__fa()
from A
將數據隱藏起來不是目的。隱藏起來然后對外提供操作數據的接口,然后就可以在接口附加上對該數據操作的限制,以此完成對數據屬性操作的嚴格限制
class Teacher:
def __init__(self,name,age):
self.__name=name
self.__age=age
def tell_info(self):
print('姓名:%s,年齡:%s' %(self.__name,self.__age))
def set_info(self,name,age):
if not isinstance(name,str):
raise TypeError('姓名必須是字符串類型')
if not isinstance(age,int):
raise TypeError('年齡必須是整型')
self.__name=name
self.__age=age
t=Teacher('egon',18)
t.tell_info()
t.set_info('egon',19)
t.tell_info()
目的是隔離復雜度
#取款是功能,而這個功能有很多功能組成:插卡、密碼認證、輸入金額、打印賬單、取錢
#對使用者來說,只需要知道取款這個功能即可,其余功能我們都可以隱藏起來,很明顯這么做
#隔離了復雜度,同時也提升了安全性
class ATM:
def __card(self):
print('插卡')
def __auth(self):
print('用戶認證')
def __input(self):
print('輸入取款金額')
def __print_bill(self):
print('打印賬單')
def __take_money(self):
print('取款')
def withdraw(self):
self.__card()
self.__auth()
self.__input()
self.__print_bill()
self.__take_money()
a=ATM()
a.withdraw()
封裝在于明確區分內外,使得類實現者可以修改封裝內的東西而不影響外部調用者的代碼。
外部調用者只需要知道函數名,只要函數名,參數不變,使用者的代碼就不需要改變。這就提供了一個良好的合作基礎。
#類的設計者
class Room:
def __init__(self,name,owner,width,length,high):
self.name=name
self.owner=owner
self.__width=width
self.__length=length
self.__high=high
def tell_area(self): #對外提供的接口,隱藏了內部的實現細節,此時我們想求的是面積
return self.__width * self.__length
#使用者
>>> r1=Room('臥室','egon',20,20,20)
>>> r1.tell_area() #使用者調用接口tell_area
#類的設計者,輕松的擴展了功能,而類的使用者完全不需要改變自己的代碼
class Room:
def __init__(self,name,owner,width,length,high):
self.name=name
self.owner=owner
self.__width=width
self.__length=length
self.__high=high
def tell_area(self): #對外提供的接口,隱藏內部實現,此時我們想求的是體積,內部邏輯變了,只需求修該下列一行就可以很簡答的實現,而且外部調用感知不到,仍然使用該方法,但是功能已經變了
return self.__width * self.__length * self.__high
#對于仍然在使用tell_area接口的人來說,根本無需改動自己的代碼,就可以用上新功能
>>> r1.tell_area()
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。