面向对象进阶2
类的封装
为什么要封装
- 封装数据的主要原因:保护隐私
- 封装方法的主要原因:隔离复杂度
两个层面的封装
封装分为两个层面
第一个层面:创建类和对象会分别创建二者的名称空间,我们只能用类名.或者对象名.的方式去访问里面的名字,这就是一种封装,对象可以拿到类名称空间中的名字,但是类没法拿到对象名称空间中的名字
第二个层面:类中吧默写属性和方法隐藏起来(或定义为私有的),只能在类的内部使用,外部无法访问,或者留下少量接口(函数)供外部访问
在python中使用双下划线的方式实现隐藏属性(设置成私有的),类中所有双下划线开头的名字如__x都会自动变形成:_类名__x的形式,这些名字只有在类内部才可以使用(如果非要在类外部使用,需要__类名__x的形式去调用(不推荐使用,丢失了封装的意义)
class A: __count=0 def __init__(self): self.__x=10 def __foo(self): print('from A') def bar(self): #这个函数就是相当于一个接口,用于外部访问来调用内部封装的属性 self.__foo() p=A() p.bar() #这个就是在类内部使用
注意:对于这一层面的封装(隐藏),我们需要在类中定义一个函数(接口函数),在他内部访问被封装的属性,然后外部就可以使用了.
这种变形需要注意的问题是:
- 这种机制也并没有整整意义上限制我们从外部直接访问属性,知道了类名和属性名就可以拼出名字:_类名__属性,然后就就可以访问了
- 变形的过程只在列定义的时候发生一次,在定义后的赋值操作不会变形
- 在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的
类的property特性
什么是property特性
property装饰器用于将被装饰的方法伪装成一个数据属性,在使用时可以不加括号而直接使用
property一般用在:本来是方法,但调用的时候希望是类似属性的调用,我们就用property
class add:
def __init__(self,a,b):
self.a=a
self.b=b
@property
def zonghe(self):
return self.a+self.b
c=add(1,2)
print(c.zonghe()) #如果没有property我们调用类内部的zhonghe函数的时候需要加括号
print(c.zonghe) #加上property后我们调用函数无序加括号
property属性的定义和调用要注意一下几点:
- 定义时,在实例方法的基础上添加@property装饰器,并且仅有一个self参数
- 调用时无需加括号
装饰器
在新式类中,具有三种@property装饰器
- @property #获取值的时候出发,不需要加括号使用并且不能加参数
- @方法名.setter #在修改的时候出发,必须加参数
- @方法名.deleter #在删除的时候触发,不能加参数
类与对象的绑定方法和非绑定方法
类中的绑定方法大致可以分为两类:绑定方法和非绑定方法,其中绑定方法又分为绑定到对象和帮定到类的方法
绑定方法
- 对象的绑定方法:没有被装饰器修饰的方法就是绑定到对象的方法,对象的绑定方法有自动传值的效果
- 类的绑定方法:方法前面有@classmethod装饰器的就是绑定到类的方法,这类方法专门为类定制.通过类名调用绑定到类的方法是,会将类本身到做参数传给类方法的第一个参数
- 非绑定方法:方法前面有@staticmethod装饰器的就是非绑定方法,这类方法和普通定义的函数没有区别,不与䣂或者对象绑定,谁都可以调用,且没有自动传值的效果