python 类的封装
一、什么是封装
在程序设计中,封装(Encapsulation)是对具体对象的一种抽象,即将某些部分隐藏起来,在程序外部看不到,其
含义是其他程序无法调用。
想要了解封装,就离不开“私有化”。也就是类的属性或者函数限制到限制在类中使用,而外部无法调用。
python中的封装和java或PHP语言的中类的私有方法、私有属性相似,但又有别于这两类语言。
二、为什么要用封装
1、封装数据:保护隐私
2、封装方法:隔离复杂度(只保留部分接口对外使用)
三、如何用封装
3.1 封装语法
已双下划线开头:
封装方法:__func
封装属性: __attr
class student(object): def __init__(self,name,age): self.__name = name # 封装的属性 self.__age = age def __name_age(self): # 封装方法 return "name: %s; age: %s"%(self.__name,self.__age) def get_name_age(self): return self.__name_age() jmz = student('jmz',13) # print(jmz.__name) #会报错AttributeError: 'student' object has no attribute '__name' print(jmz.get_name_age()) ''' 输出结果 name: jmz; age: 13 '''
3.2 封装后的类对象__dict__属性
print(jmz.__dict__) ''' 输出结果 {'_student__name': 'jmz', '_student__age': 13} '''
当我们打印出类的对象属性时,我们发现了
{'_student__name': 'jmz', '_student__age': 13}
这里有我们当初调用类时的数据,只是属性前加了_类名,此时我们打印一下能否打印出这个属性
print(jmz._student__name) ''' 输出结果 jmz '''
结论:
1、Python 的封装并不是真正意义上的外部无法调用,
与java ,PHP不同,Python如果调用封装的属性或方法,需要在方法和属性前加_类名(如果真的这样做了,那么与非封装方法、属性有什么区别呢)
3.3 父类与子类的封装方法
class A: __x = 'A' # 变形为_A__x def get_x(self): print(self.__x) class A1(A): # A1 继承了 A 的方法和属性 __x = 'A1' # 变形为_A1__X obj = A1() obj.get_x() ''' 输出结果 A '''
A1类的封装属性并没有覆盖A类的封装属性
print(A.__dict__) print(A1.__dict__) ''' {'__module__': '__main__', '_A__x': 'A', 'get_x': <function A.get_x at 0x00000000024D9950>, '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None} {'__module__': '__main__', '_A1__x': 'A1', '__doc__': None} '''
A1类和A类的__X 封装属性实际上已经转变成_A__X ,_A1__X
结论:
1、 子类的封装属性或方法并不会覆盖父类的封装属性或方法
2、 子类或父类的封装属性或封装方法是语法上变形过了
3.4 类的封装到底发生了什么?
class foo: def __init__(self,x,y): self.__x = x # 变形为_foo__x self.__y = y # 变形为_foo__y obj = foo('x','y') obj.__z = 'z' # 任然是__z print(obj.__dict__) ''' 输出结果 {'_foo__x': 'x', '_foo__y': 'y', '__z': 'z'} '''
注意:
1、类的封装不是真正意义上的“私有化”,而是一个语法上的变形
2、类的封装属性或方式,其实在定义阶段就已经进行了语法上的变形
3、类的调用阶段,再进行封装语法已经没有任何用处了
四、封装之property
4.1 什么是property
property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值(就是一个装饰器)
注意:被property装饰的属性会优先于对象的属性被使用,而被propery装饰的属性,分成三种:property、被装饰
的函数名.setter、被装饰的函数名.deleter(都是以装饰器的形式)。
4.2 如何使用property
# 体重指数 = 体重/(身高* 2) # 偏瘦 <=18.5 # 正常 18.5 ~22.9 # 超重 >22.9 class people: def __init__(self,weight,height): self.weight = weight self.height = height @property # 只要在方法的上方加上一个装饰器 @property ,就可以将方法当做属性使用 def bmi(self): # 体重指数 更像是人的一个属性值,那不应该是一个功能 return self.weight / (self.height * 2) jmz = people(66,1.75) print(jmz.bmi)
4.3 关于property 特殊属性的删改
# 体重指数 = 体重/(身高* 2) # 偏瘦 <=18.5 # 正常 18.5 ~22.9 # 超重 >22.9 class people: def __init__(self,weight,height): self.weight = weight self.height = height @property # 只要在方法的上方加上一个装饰器 @property ,就可以将方法当做属性使用 def bmi(self): # 体重指数 更像是人的一个属性值,那不应该是一个功能 return self.weight / (self.height * 2) @bmi.setter # 改 特殊属性方法名.setter 必须在特殊属性方法的下方 def bmi(self,value): print('改属性值不可更改') @bmi.deleter # 删 特殊属性方法名.deleter 必须在特殊属性方法的下方 def bmi(self): print('改属性值不可删除') jmz = people(66,1.75) print(jmz.bmi) jmz.bmi = 12 del jmz.bmi ''' 输出 18.857142857142858 改属性值不可更改 改属性值不可删除 '''
本文引用:https://www.cnblogs.com/Michael--chen/p/6740455.html

浙公网安备 33010602011771号