封装指的是将对象的状态信息隐藏在对象内部,不允许外部直接访问对象内部信息,而是通过该类提供的方法来实现对内部信息的操作和访问;封装的含义,实际上,是把该隐藏的隐藏起来,该暴露的暴露出来;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'