封裝 1.為什麼要封裝? 封裝就是要把數據屬性和方法的具體實現細節隱藏起來,只提供一個介面。封裝可以不用關心對象是如何構建的 2.封裝包括數據的封裝和函數的封裝,數據的封裝是為了保護隱私,函數的封裝是為了隔離複雜度 3.數據的封裝就是在屬性前面加一個__ 咦,報錯了,讓我們打開對象的名稱空間,看看發 ...
封裝
1.為什麼要封裝?
封裝就是要把數據屬性和方法的具體實現細節隱藏起來,只提供一個介面。封裝可以不用關心對象是如何構建的
2.封裝包括數據的封裝和函數的封裝,數據的封裝是為了保護隱私,函數的封裝是為了隔離複雜度
3.數據的封裝就是在屬性前面加一個__
class People: def __init__(self,name,age,salary): self.name=name self.age=age self.__salary=salary p=People('zhang',19,100000) print(p.name)#zhang print(p.age)#19 print(p.__salary)#AttributeError: 'People' object has no attribute '__salary'
咦,報錯了,讓我們打開對象的名稱空間,看看發生了什麼
print(p.__dict__)#{'name': 'zhang', 'age': 19, '_People__salary': 100000}
哦,原來python把__salary變形成了_People__salary,再來一遍
print(p._People__salary)#100000
所以,Python中並沒有絕對的隱藏,只要你知道了上面這個,就無所謂隱藏了
這些變形操作,只在類的定義階段或者對象定義(實例化階段)階段發生
雖然在外部無法直接訪問加了__的屬性,但是在類內部可以訪問到,可以這麼理解,在定義階段,只要遇到__開頭的,Python解釋器自動識別為_類名__屬性,所以在類內部是可以訪問到的,這樣的話,我們就可以搞一點小事情了
先來看這個
class A: def foo(self): print('from A foo') self.bar() def bar(self): print('from A bar') class B(A): def bar(self): print('from B bar') b=B() b.foo() #from A foo
#from B bar 別想多了,調用函數時別看定義位置,要看調用位置
如果就是想調用父類的bar()函數呢?該怎麼做
class A: def foo(self): print('from A foo') self.__bar() def __bar(self): print('from A bar') class B(A): def __bar(self): print('from B bar') b=B() b.foo() #from A foo #from A bar 有沒有感受到編程的享受
4.封裝的應用
1)不讓外界看到我們的數據屬性是怎麼定義的,只能通過我們提供的介面,看到我們允許外界看到的內容
class People: def __init__(self,name,age,height,weight,hobby): self.__name=name self.__age=age self.__height=height self.__weight=weight self._hobby=hobby def tell_info(self): print(''' name:%s age:%s height:%s weeight:%s '''%(self.__name,self.__age, self.__height,self.__weight)) p=People('zhang',18,1.90,75,'read') p.tell_info()
2)更常用的場景是,我們可以限制數據的類型,添加自己的邏輯以後再封裝好給用戶
def tell_name(self): print(self.__name) #修改名字 def set_name(self,new): if not isinstance(new,str): raise TypeError('名字必須是字元串類型') self.__name=new
5.看我們上面的操作,用戶查看名字的時候還得p.tell_name(),本來是個數據屬性,卻被我們搞得變成了一個函數,怎麼偽裝一下呢,就可以用到property這個內置函數了
class People: def __init__(self,name,age,height,weight,hobby): self.__name=name self.__age=age self.__height=height self.__weight=weight self._hobby=hobby @property def name(self): return self.__name p=People('zhang',18,1.90,75,'read') print(p.name)#zhang
數據屬性還應該有修改,刪除操作
@property def name(self): return self.__name #name已經被property修飾過,就有setter和deleter @name.setter def name(self,new): if not isinstance(new,str): raise TypeError('名字必須是字元串類型') self.__name=new @name.deleter def name(self): del self.__name p = People('zhang', 18, 1.90, 75, 'read') print(p.name)#zhang p.name='can' #修改 print(p.name)#can del p.name #刪除 print(p.name)#AttributeError: 'People' object has no attribute '_People__name'