您好,登錄后才能下訂單哦!
python中用雙下劃線開(kāi)頭的方式把屬性隱藏起來(lái)(設(shè)置成私有的)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author: vita
#其實(shí)這僅僅這是一種變形操作
#類(lèi)中所有雙下劃線開(kāi)頭的名稱(chēng)如__x都會(huì)自動(dòng)變形成:_類(lèi)名__x的形式:
class A:
__N=0 #類(lèi)的數(shù)據(jù)屬性就應(yīng)該是共享的,但是語(yǔ)法上是可以把類(lèi)的數(shù)據(jù)屬性設(shè)置成私有的如__N,會(huì)變形為_(kāi)A__N
def __init__(self):
self.__X=10 #類(lèi)定義時(shí)就變形為self._A__X
def __foo(self): #類(lèi)定義時(shí)就變形為_(kāi)A__foo
print('from A')
def bar(self):
self.__foo() #只有在類(lèi)內(nèi)部才可以通過(guò)__foo的形式訪問(wèn)到.
a = A()
print("a.__dict__",a.__dict__)
#定義后的賦值操作,不會(huì)變形為_(kāi)類(lèi)名__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是可以訪問(wèn)到的,即這種操作并不是嚴(yán)格意義上的限制外部訪問(wèn),僅僅只是一種語(yǔ)法意義上的變形
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
這種自動(dòng)變形的特點(diǎn):
1.類(lèi)中定義的__x只能在內(nèi)部使用,如self.__x,引用的就是變形的效果。
2.這種變形其實(shí)是針對(duì)外部的變形,在外部是無(wú)法通過(guò)__x這個(gè)名字訪問(wèn)到的。
3.在子類(lèi)定義的__x不會(huì)覆蓋在父類(lèi)定義的__x,
因?yàn)樽宇?lèi)中變形成了:_子類(lèi)名__x,
而父類(lèi)中變形成了:_父類(lèi)名__x,即雙下劃線開(kāi)頭的屬性在繼承給子類(lèi)時(shí),子類(lèi)時(shí)無(wú)法覆蓋的。
這種變形要注意的問(wèn)題:
"1.這種機(jī)制并沒(méi)有真正意義上限制我們從外部直接訪問(wèn)屬性,知道了類(lèi)名和屬性名還可以拼出名字:_類(lèi)名__屬性,然后就可以訪問(wèn)了,如a._A__N或A._A__N"
"2.變形的過(guò)程只在類(lèi)定義時(shí)發(fā)生一次,在定義后的賦值操作,不會(huì)發(fā)生變形"
print("a.__dict__",a.__dict__)
#定義后的賦值操作,不會(huì)變形為_(kāi)類(lèi)名__N
a.__Y=1
print("a.__dict__",a.__dict__)
a.__dict__ {'_A__X': 10}
a.__dict__ {'_A__X': 10, '__Y': 1}#這里依舊是__Y,并沒(méi)變形為_(kāi)A__Y
"3.在繼承中,父類(lèi)如果不想讓子類(lèi)覆蓋自己的方法,可以把方法定義為私有的"
#正常情況
>>> class A:
... def fa(self):
... print('from A')
... def test(self):
... self.fa() #這里先到對(duì)象自身的類(lèi)中找,找不到再到A類(lèi)中找
...
>>> class B(A):
... def fa(self):
... print('from B')
...
>>> b=B()
>>> b.test()
from B
#把fa定義成私有的,即__fa
>>> class A:
... def __fa(self): #在定義時(shí)就變形為_(kāi)A__fa
... print('from A')
... def test(self):
... self.__fa() #在定義階段,變形為self._A__fa,所以只會(huì)與自己所在的類(lèi)為準(zhǔn)
...
>>> class B(A):
... def __fa(self): #在定義階段,變形為self._B__fa
... print('from B')
...
>>> b=B()
>>> b.test() #注意這里調(diào)用的self.__fa()為類(lèi)A中的__fa()
from A
將數(shù)據(jù)隱藏起來(lái)不是目的。隱藏起來(lái)然后對(duì)外提供操作數(shù)據(jù)的接口,然后就可以在接口附加上對(duì)該數(shù)據(jù)操作的限制,以此完成對(duì)數(shù)據(jù)屬性操作的嚴(yán)格限制
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('姓名必須是字符串類(lèi)型')
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()
目的是隔離復(fù)雜度
#取款是功能,而這個(gè)功能有很多功能組成:插卡、密碼認(rèn)證、輸入金額、打印賬單、取錢(qián)
#對(duì)使用者來(lái)說(shuō),只需要知道取款這個(gè)功能即可,其余功能我們都可以隱藏起來(lái),很明顯這么做
#隔離了復(fù)雜度,同時(shí)也提升了安全性
class ATM:
def __card(self):
print('插卡')
def __auth(self):
print('用戶認(rèn)證')
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()
封裝在于明確區(qū)分內(nèi)外,使得類(lèi)實(shí)現(xiàn)者可以修改封裝內(nèi)的東西而不影響外部調(diào)用者的代碼。
外部調(diào)用者只需要知道函數(shù)名,只要函數(shù)名,參數(shù)不變,使用者的代碼就不需要改變。這就提供了一個(gè)良好的合作基礎(chǔ)。
#類(lèi)的設(shè)計(jì)者
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): #對(duì)外提供的接口,隱藏了內(nèi)部的實(shí)現(xiàn)細(xì)節(jié),此時(shí)我們想求的是面積
return self.__width * self.__length
#使用者
>>> r1=Room('臥室','egon',20,20,20)
>>> r1.tell_area() #使用者調(diào)用接口tell_area
#類(lèi)的設(shè)計(jì)者,輕松的擴(kuò)展了功能,而類(lèi)的使用者完全不需要改變自己的代碼
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): #對(duì)外提供的接口,隱藏內(nèi)部實(shí)現(xiàn),此時(shí)我們想求的是體積,內(nèi)部邏輯變了,只需求修該下列一行就可以很簡(jiǎn)答的實(shí)現(xiàn),而且外部調(diào)用感知不到,仍然使用該方法,但是功能已經(jīng)變了
return self.__width * self.__length * self.__high
#對(duì)于仍然在使用tell_area接口的人來(lái)說(shuō),根本無(wú)需改動(dòng)自己的代碼,就可以用上新功能
>>> r1.tell_area()
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。