日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python 封装_Python 面向对象三大特性之封装

發布時間:2024/1/23 python 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python 封装_Python 面向对象三大特性之封装 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

封裝

  • 定義:隱藏對象的屬性和實現細節,僅對外提供公共訪問方式。
  • 【好處】
    • 將變化隔離;
    • 便于使用;
    • 提高復用性;
    • 提高安全性;
  • 【封裝原則】
    • 將不需要對外提供的內容都隱藏起來;
    • 把屬性都隱藏,提供公共方法對其訪問。

PS私有變量和私有方法

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

私有變量

#其實這僅僅這是一種變形操作 #類中所有雙下劃線開頭的名稱如__x都會自動變形成:_類名__x的形式:class A:__N=0 #類的數據屬性就應該是共享的,但是語法上是可以把類的數據屬性設置成私有的如__N,會變形為_A__Ndef __init__(self):self.__X=10 #變形為self._A__Xdef __foo(self): #變形為_A__fooprint('from A')def bar(self):self.__foo() #只有在類內部才可以通過__foo的形式訪問到.#A._A__N是可以訪問到的,即這種操作并不是嚴格意義上的限制外部訪問,僅僅只是一種語法意義上的變形

自動變形的特點

  • 類中定義的__x只能在內部使用,如self.__x,引用的就是變形的結果。
  • 這種變形其實正是針對外部的變形,在外部是無法通過__x這個名字訪問到的。
  • 在子類定義的__x不會覆蓋在父類定義的__x,因為子類中變形成了:_子類名__x,而父類中變形成了:_父類名__x,即雙下滑線開頭的屬性在繼承給子類時,子類是無法覆蓋的。

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

  • 這種機制也并沒有真正意義上限制我們從外部直接訪問屬性,知道了類名和屬性名就可以拼出名字:_類名__屬性,然后就可以訪問了,如a._A__N
  • 變形的過程只在類的內部生效,在定義后的賦值操作,不會變形

私有方法

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

#正常情況 >>> 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=nameself.owner=ownerself.__width=widthself.__length=lengthself.__high=highdef tell_area(self): #對外提供的接口,隱藏了內部的實現細節,此時我們想求的是面積return self.__width * self.__length#使用者 >>> r1=Room('臥室','run',20,20,20) >>> r1.tell_area() #使用者調用接口tell_area#類的設計者,輕松的擴展了功能,而類的使用者完全不需要改變自己的代碼 class Room:def __init__(self,name,owner,width,length,high):self.name=nameself.owner=ownerself.__width=widthself.__length=lengthself.__high=highdef 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=nameself.weight=weightself.height=height@propertydef bmi(self):return self.weight / (self.height**2)p1=People('egon',75,1.85) print(p1.bmi)

圓的周長和面積

import math class Circle:def __init__(self,radius): #圓的半徑radiusself.radius=radius@propertydef area(self):return math.pi * self.radius**2 #計算面積@propertydef 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

此時的特性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 #將所有的數據屬性都隱藏起來@propertydef name(self):return self.__NAME #obj.name訪問的是self.__NAME(這也是真實值的存放位置)@name.setterdef name(self,value):if not isinstance(value,str): #在設定值之前進行類型檢查raise TypeError('%s must be str' %value)self.__NAME=value #通過類型檢查后,將值value存放到真實的位置self.__NAME@name.deleterdef 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:@propertydef AAA(self):print('get的時候運行我啊')@AAA.setterdef AAA(self,value):print('set的時候運行我啊')@AAA.deleterdef AAA(self):print('delete的時候運行我啊')#只有在屬性AAA定義property后才能定義AAA.setter,AAA.deleter f1=Foo() f1.AAA f1.AAA='aaa' del f1.AAAclass 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

用法

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

classmethod

class Classmethod_Demo():role = 'dog'@classmethoddef func(cls):print(cls.role)Classmethod_Demo.func()

staticmethod

class Staticmethod_Demo():role = 'dog'@staticmethoddef func():print("當普通方法用")Staticmethod_Demo.func()

總結

以上是生活随笔為你收集整理的python 封装_Python 面向对象三大特性之封装的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。