python開發物件導向基礎:封裝

來源:互聯網
上載者:User

標籤:結果   而且   print   setter   parent   name   拋出異常   dog   複用   

一,封裝

【封裝】

         隱藏對象的屬性和實現細節,僅對外提供公用訪問方式。

【好處】 

1. 將變化隔離; 

2. 便於使用;

3. 提高複用性; 

4. 提高安全性;

【封裝原則】

      1. 將不需要對外提供的內容都隱藏起來;

      2. 把屬性都隱藏,提供公用方法對其訪問。

私人變數和私人方法

在python中用雙底線開頭的方式將屬性隱藏起來(設定成私人的)

私人變數
#其實這僅僅這是一種變形操作#類中所有雙底線開頭的名稱如__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__N是可以訪問到的,即這種操作並不是嚴格意義上的限制外部存取,僅僅只是一種文法意義上的變形

這種自動變形的特點:

1.類中定義的__x只能在內部使用,如self.__x,引用的就是變形的結果

2.這種變形其實正是針對外部的變形,在外部是無法通過__x這個名字訪問到的。

3.在子類定義的__x不會覆蓋在父類定義的__x,因為子類中變形成了:_子類名__x,而父類中變形成了:_父類名__x,即雙下滑線開頭的屬性在繼承給子類時,子類是無法覆蓋的。

 

這種變形需要注意的問題是:

1.這種機制也並沒有真正意義上限制我們從外部直接存取屬性,知道了類名和屬性名稱就可以拼出名字:_類名__屬性,然後就可以訪問了,如a._A__N

2.變形的過程只在類的定義是發生一次,在定義後的賦值操作,不會變形

私人方法

3.在繼承中,父類如果不想讓子類覆蓋自己的方法,可以將方法定義為私人的

#正常情況>>> class A:...     def fa(self):...         print(‘from A‘)...     def test(self):...         self.fa()... >>> 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() #只會與自己所在的類為準,即調用_A__fa... >>> class B(A):...     def __fa(self):...         print(‘from B‘)... >>> b=B()>>> b.test()from A

 

封裝與擴充性

封裝在於明確區分內外,使得類實現者可以修改封裝內的東西而不影響外部調用者的代碼;而外部使用用者只知道一個介面(函數),只要介面(函數)名、參數不變,使用者的代碼永遠無需改變。這就提供一個良好的合作基礎——或者說,只要介面這個基礎約定不變,則代碼改變不足為慮。

#類的設計者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()

 

property屬性

什麼是特性property

property是一種特殊的屬性,訪問它時會執行一段功能(函數)然後傳回值

例一:BMI指數(bmi是計算而來的,但很明顯它聽起來像是一個屬性而非方法,如果我們將其做成一個屬性,更便於理解)成人的BMI數值:過輕:低於18.5正常:18.5-23.9過重:24-27肥胖:28-32非常肥胖, 高於32  體質指數(BMI)=體重(kg)÷身高^2(m)  EX:70kg÷(1.75×1.75)=22.86
例一
class People:    def __init__(self,name,weight,height):        self.name=name        self.weight=weight        self.height=height    @property    def bmi(self):        return self.weight / (self.height**2)p1=People(‘egon‘,75,1.85)print(p1.bmi)
View Code
import mathclass Circle:    def __init__(self,radius): #圓的半徑radius        self.radius=radius    @property    def area(self):        return math.pi * self.radius**2 #計算面積    @property    def perimeter(self):        return 2*math.pi*self.radius #計算周長c=Circle(10)print(c.radius)print(c.area) #可以向訪問資料屬性一樣去訪問area,會觸發一個函數的執行,動態計算出一個值print(c.perimeter) #同上‘‘‘輸出結果:314.159265358979362.83185307179586‘‘‘
例二:圓的周長和面積
#注意:此時的特性area和perimeter不能被賦值c.area=3 #為特性area賦值‘‘‘拋出異常:AttributeError: can‘t set attribute‘‘‘

為什麼要用property

將一個類的函數定義成特性以後,對象再去使用的時候obj.name,根本無法察覺自己的name是執行了一個函數然後計算出來的,這種特性的使用方式遵循了統一訪問的原則

除此之外,看下

ps:物件導向的封裝有三種方式:【public】這種其實就是不封裝,是對外公開的【protected】這種封裝方式對外不公開,但對朋友(friend)或者子類(形象的說法是“兒子”,但我不知道為什麼大家 不說“女兒”,就像“parent”本來是“父母”的意思,但中文都是叫“父類”)公開【private】這種封裝對誰都不公開

python並沒有在文法上把它們三個內建到自己的class機制中,在C++裡一般會將所有的所有的資料都設定為私人的,然後提供set和get方法(介面)去設定和擷取,在python中通過property方法可以實現

class Foo:    def __init__(self,val):        self.__NAME=val #將所有的資料屬性都隱藏起來    @property    def name(self):        return self.__NAME #obj.name訪問的是self.__NAME(這也是真實值的存放位置)    @name.setter    def name(self,value):        if not isinstance(value,str):  #在設定值之前進行類型檢查            raise TypeError(‘%s must be str‘ %value)        self.__NAME=value #通過類型檢查後,將值value存放到真實的位置self.__NAME    @name.deleter    def name(self):        raise TypeError(‘Can not delete‘)f=Foo(‘egon‘)print(f.name)# f.name=10 #拋出異常‘TypeError: 10 must be str‘del f.name #拋出異常‘TypeError: Can not delete‘

一個靜態屬性property本質就是實現了get,set,delete三種方法

class Foo:    @property    def AAA(self):        print(‘get的時候運行我啊‘)    @AAA.setter    def AAA(self,value):        print(‘set的時候運行我啊‘)    @AAA.deleter    def AAA(self):        print(‘delete的時候運行我啊‘)#只有在屬性AAA定義property後才能定義AAA.setter,AAA.deleterf1=Foo()f1.AAAf1.AAA=‘aaa‘del f1.AAA
View Code
class Foo:    def get_AAA(self):        print(‘get的時候運行我啊‘)    def set_AAA(self,value):        print(‘set的時候運行我啊‘)    def delete_AAA(self):        print(‘delete的時候運行我啊‘)    AAA=property(get_AAA,set_AAA,delete_AAA) #內建property三個參數與get,set,delete一一對應f1=Foo()f1.AAAf1.AAA=‘aaa‘del f1.AAA
View Code

怎麼用?

class Goods:    def __init__(self):        # 原價        self.original_price = 100        # 折扣        self.discount = 0.8    @property    def price(self):        # 實際價格 = 原價 * 折扣        new_price = self.original_price * self.discount        return new_price    @price.setter    def price(self, value):        self.original_price = value    @price.deleter    def price(self):        del self.original_priceobj = Goods()obj.price         # 擷取商品價格obj.price = 200   # 修改商品原價print(obj.price)del obj.price     # 刪除商品原價

 

classmethod

 

class Classmethod_Demo():    role = ‘dog‘    @classmethod    def func(cls):        print(cls.role)
Classmethod_Demo.func()

 

staticmethod

 

class Staticmethod_Demo():    role = ‘dog‘    @staticmethod    def func():        print("當普通方法用")
Staticmethod_Demo.func()

python開發物件導向基礎:封裝

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.