封裝指的是將對象的狀態信息隱藏在對象內部,不允許外部直接訪問對象內部信息,而是通過該類提供的方法來實現對內部信息的操作和訪問;封裝的含義,實際上,是把該隱藏的隱藏起來,該暴露的暴露出來;Python只需要將類的成員名為以雙下划線開頭,就可以隱藏類中的成員。
一、封裝數據屬性
例:
class Fraction: __grade = 0 def __init__(self,name): self.__name = name def setting_grade(self,var): if isinstance(var,int) and var >= 0 and var <=100: Fraction.__grade = var else: print ('請輸入正確的分數!') def setting_name(self,set_name): if isinstance(set_name,str): self.__name = set_name else: print ('請輸入正確的姓名!') def get_fraction(self): print ('%s分數是:%s'%(self.__name,Fraction.__grade)) F = Fraction('小黃') print (F.__grade) # 報錯 AttributeError: 'Fraction' object has no attribute '__grade' print (F.__name) # 報錯 AttributeError: 'Fraction' object has no attribute '__name' F.get_fraction() # 打印 小黃分數是:0 F.setting_name('小明') F.setting_grade(100) # setting_grade()、setting_name()會對用戶設置grade、name進行控制,符合條件才能允許設置 F.get_fraction() # 打印 小明分數是:100 # 可以使用 _類名來訪問或修改對象的實例變量 print (F._Fraction__grade) # 打印 100 print (F._Fraction__name) # 打印 小明
上面例子中,代碼print (F.__grade)和print (F.__name)直接訪問私有變量會報錯setting_grade()、setting_name()方法用於對grade、name進行設置,只有符合條件才能允許設置;print (F._Fraction__grade)和print (F._Fraction__name)通過 _類名來訪問對象的實例變量(通常不要這么做),可以看出Python並沒有實現真正隱藏,只是改變以雙下划線開頭的變量,在這些變量前添加單下畫線和變量名。
二、封裝函數屬性
例:
class SumFraction: def __init__(self,usually,test): self.__usually = usually self.__test = test def set_usually_score(self,usually_var): if isinstance(usually_var,int) and usually_var >= 0 and usually_var <=100: self.__usually = usually_var else: print ('請輸入正確的分數!') def set_test_score(self,test_var): if isinstance(test_var,int) and test_var >= 0 and test_var <=100: self.__test = test_var else: print ('請輸入正確的分數!') def __calculation(self): # 私有方法,只能內部使用,對外部隱藏運算邏輯 return self.__usually * 0.3 + self.__test * 0.7 def final_grade(self): return self.__calculation() S = SumFraction(100,50) print (S.final_grade()) # 打印 65.0 print (S.__calculation()) # 調用隱藏的__calculation()方法,會報錯 AttributeError: 'SumFraction' object has no attribute '__calculation' print (S._SumFraction__calculation()) # 可以使用_類名方法名調用(不推薦這樣做),打印 65.0 # 修改__usually和__test S.set_usually_score(70) S.set_test_score(100) print (S.final_grade()) # 通過final_grade()方法內部進行訪問__calculation()私有方法,打印 91.0
上面代碼中,set_usually_score()和set_test_score()用於對usually 、test進行設置;__calculation()是私有方法,默認是隱藏的,只允許內部使用,外部使用會報錯,當然也可以使用_類名方法名調用,但並不推薦這么做;print (S.final_grade())通過final_grade()方法內部訪問__calculation()私有方法。
三、property
先看一下幫助文檔:
>>> help(property) Help on class property in module builtins: class property(object) | property(fget=None, fset=None, fdel=None, doc=None) | | Property attribute. | | fget | function to be used for getting an attribute value | fset | function to be used for setting an attribute value | fdel | function to be used for del'ing an attribute | doc | docstring | | Typical use is to define a managed attribute x: | | class C(object): | def getx(self): return self._x | def setx(self, value): self._x = value | def delx(self): del self._x | x = property(getx, setx, delx, "I'm the 'x' property.") | | Decorators make defining new properties or modifying existing ones easy: | | class C(object): | @property | def x(self): | "I am the 'x' property." | return self._x | @x.setter | def x(self, value): | self._x = value | @x.deleter | def x(self): | del self._x | | Methods defined here: | | __delete__(self, instance, /) | Delete an attribute of instance. | | __get__(self, instance, owner, /) | Return an attribute of instance, which is of type owner. | | __getattribute__(self, name, /) | Return getattr(self, name). | | __init__(self, /, *args, **kwargs) | Initialize self. See help(type(self)) for accurate signature. | | __set__(self, instance, value, /) | Set an attribute of instance to value. | | deleter(...) | Descriptor to change the deleter on a property. | | getter(...) | Descriptor to change the getter on a property. | | setter(...) | Descriptor to change the setter on a property. | | ---------------------------------------------------------------------- | Static methods defined here: | | __new__(*args, **kwargs) from builtins.type | Create and return a new object. See help(type) for accurate signature. | | ---------------------------------------------------------------------- | Data descriptors defined here: | | __isabstractmethod__ | | fdel | | fget | | fset
@property 可以在一個類中把方法變成同名屬性調用,能用屬性的方式來訪問該屬性。
@x.setter 表示可寫,最大作用是用於限制屬性的定義,x是被@property修飾的方法名,@x.setter修飾的方法名@property修飾的方法名必須同名。
@x.deleter 表示可刪除,x是被@property修飾的方法名,@x.deleter修飾的方法名@property修飾的方法名必須同名。
例:
class SumFraction: def __init__(self,value): self.__score = value @property # 讀 def score(self): print ('讀......') return self.__score @score.setter # 寫 def score(self,var): print ('寫......') if isinstance(var,int) and var >= 0 and var <=100: self.__score = var return self.__score else: print ('請輸入正確的分數!') return @score.deleter # 刪除 def score(self): print ("刪除self.__score......") del self.__score S = SumFraction(100) S.score = 80 # 寫,打印 改...... print (S.score) ''' 讀,打印 讀...... 80 ''' del S.score # 刪除,打印 刪除self.__score...... print (S.score) # __score已被刪除,打印 AttributeError: 'SumFraction' object has no attribute '_SumFraction__score'
用property類來實現,例:
class SumFraction: def __init__(self,value): self.__score = value def get_score(self): print ('讀......') return self.__score def set_score(self,var): print ('寫......') if isinstance(var,int) and var >= 0 and var <=100: self.__score = var return self.__score else: print ('請輸入正確的分數!') return def del_score(self): print ("刪除self.__score......") del self.__score score = property(get_score,set_score,del_score,'這里是屬性含義~ ') S = SumFraction(100) S.score = 80 # 寫,打印 改...... print (S.score) ''' 讀,打印 讀...... 80 ''' print (SumFraction.score.__doc__) # 屬性含義,打印 這里是屬性含義~ del S.score # 刪除,打印 刪除self.__score...... print (S.score) # __score已被刪除,打印 AttributeError: 'SumFraction' object has no attribute '_SumFraction__score'