python之封裝

      網友投稿 1038 2025-03-31

      【封裝】

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

      【好處】

      1. 將變化隔離;

      2. 便于使用;

      3. 提高復用性;

      4. 提高安全性;

      【封裝原則】

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

      python之封裝

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

      1、私有變量和私有方法

      Python中用雙下劃線開頭的方式將屬性隱藏起來(設置成私有的)

      1

      2

      3

      4

      #其實這僅僅這是一種變形操作#類中所有雙下劃線開頭的名稱如__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.在繼承中,父類如果不想讓子類覆蓋自己的方法,可以將方法定義為私有的

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      #正常情況>>>?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

      2、封裝與擴展性

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

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

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

      3、property屬性

      什么是特性property

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

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      例一: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

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      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)

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      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.1592653589793

      62.83185307179586

      '''

      1

      2

      3

      4

      #注意:此時的特性area和perimeter不能被賦值c.area=3?#為特性area賦值'''

      拋出異常:

      AttributeError:?can't? set? attribute

      '''

      為什么要用property

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

      除此之外,看下

      1

      2

      3

      4

      5

      6

      7

      ps:面向對象的封裝有三種方式:

      【public】

      這種其實就是不封裝,是對外公開的

      【protected】

      這種封裝方式對外不公開,但對朋友(friend)或者子類(形象的說法是“兒子”,但我不知道為什么大家?不說“女兒”,就像“parent”本來是“父母”的意思,但中文都是叫“父類”)公開

      【private】

      這種封裝對誰都不公開

      Python并沒有在語法上把它們三個內建到自己的class機制中,在C++里一般會將所有的所有的數據都設置為私有的,然后提供set和get方法(接口)去設置和獲取,在python中通過property方法可以實現

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      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三種方法

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      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.AAA

      f1.AAA = 'aaa' del? f1.AAA

      1

      2

      3

      4

      5

      6

      7

      8

      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.AAA

      f1.AAA = 'aaa' del? f1.AAA

      怎么用?

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      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_price

      obj? =? Goods()

      obj.price????????? #?獲取商品價格obj.price?=?200???#?修改商品原價print(obj.price)

      del? obj.price????? #?刪除商品原價

      4、classmethod

      1

      2

      3

      4

      class? Classmethod_Demo():????role? =? 'dog'???? @ classmethod

      def? func( cls ):???????? print ( cls .role)

      Classmethod_Demo.func()

      5、staticmethod

      1

      2

      3

      4

      5

      class? Staticmethod_Demo():????role? =? 'dog'???? @ staticmethod

      def? func():

      print ( "當普通方法用" )

      Staticmethod_Demo.func()

      練習1:

      1

      2

      3

      4

      class? Foo:???? def? func( self ):???????? print ( 'in?father' ) class? Son(Foo):???? def? func( self ):???????? print ( 'in?son' )

      s? =? Son()

      s.func() #?請說出上面一段代碼的輸出并解釋原因?

      練習2:

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      class? A:????__role? =? 'CHINA'???? @ classmethod

      def? show_role( cls ):

      print ( cls .__role)

      @ staticmethod

      def? get_role():

      return? A.__role

      @ property

      def? role( self ):

      return? self .__role

      a? =? A()

      print (a.role)

      print (a.get_role())

      a.show_role() #?__role在類中有哪些身份?#?以上代碼分別輸出哪些內容?#?這三個裝飾器分別起了什么作用?有哪些區別?

      Python

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:MROUND(mround函數)
      下一篇:excel保存了還能還原到保存之前的嗎?(保存過的excel怎么恢復之前的)
      相關文章
      亚洲午夜成激人情在线影院| 久久久久亚洲精品影视| 亚洲人成网7777777国产| 亚洲A∨午夜成人片精品网站| 亚洲国产片在线观看| 18gay台湾男同亚洲男同| 亚洲av丰满熟妇在线播放| 亚洲va中文字幕无码久久不卡| 亚洲人成伊人成综合网久久久| 亚洲偷自拍拍综合网| 亚洲日韩在线观看免费视频| 亚洲av无码天堂一区二区三区 | 中文字幕 亚洲 有码 在线| 亚洲一级毛片免费看| 亚洲美女一区二区三区| 亚洲高清不卡视频| 亚洲高清不卡视频| 亚洲国产模特在线播放| 亚洲av无码电影网| 国产 亚洲 中文在线 字幕| 亚洲熟妇丰满xxxxx| 精品久久久久亚洲| 亚洲国产人成精品| 久久久久亚洲精品中文字幕| 中文字幕亚洲乱码熟女一区二区| 中文字幕中韩乱码亚洲大片| 亚洲精品狼友在线播放| 亚洲VA中文字幕不卡无码| 亚洲国产精品人久久| 亚洲美女视频免费| 亚洲六月丁香婷婷综合| 亚洲高清毛片一区二区| mm1313亚洲精品无码又大又粗 | 色婷婷六月亚洲婷婷丁香| 亚洲综合激情视频| 亚洲一区动漫卡通在线播放| 亚洲精品蜜夜内射| 亚洲人成网站色在线入口| 亚洲人成色777777在线观看| 亚洲嫩模在线观看| 亚洲av一本岛在线播放|