前言
面向对象编程有三大特性:封装、继承、多态,封装则是基石。封装,顾名思义把东西封好并装在一起,即上文所说的组合、打包!封装好的属性,我们可以对其进行严格控制,即隐藏属性与开放接口!
1、隐藏属性
1.1、何为隐藏属性?
即将封装好的属性进行隐藏操作,使其不直接对外暴露!Python为class提供了一种语法,在名称前面加双下划线即为隐藏!这其实是一种重命名操作,隐藏的属性在定义阶段时被重命名!如下所示:
class Student:
__province = 'GuangDong' # rename为_Student.__province
def __print_str(self): # rename为_Student.__print_str
print('我是', self)
stu1 = Student()
print(stu1.__province, stu1.__print_str) # 无论直接访问province还是__province都无法访问得到属性
# 执行得到结果
AttributeError: 'Student' object has no attribute '__province'
上面说过,这仅仅是一种重命名操作!因此,在得出类名与属性名的情况下,是可以推算出真名的!
print(stu1._Student__province)
# 执行得到结果
GuangDong
因为隐藏是在定义阶段所进行,因此在类的内部可以直接访问双下划线的名称,之后再调用对象、类进行赋值的操作是不会隐藏的!因为它是在定义阶段所进行!
class Student:
__province = 'GuangDong' # rename为_Student.__province
def __print_str(self): # rename为_Student.__print_str
print('我是', self)
print(__province) # 可直接访问
stu1 = Student()
stu1.age = 18 # 定义完后再赋值,不会隐藏!
print(stu1.age)
# 执行得到结果
GuangDong
18
2、开放接口
属性是拿来用的,因此隐藏后主要是不让使用者直接操作,我们需要提供一个接口给人访问,也是为了控制对属性的操作!很明显,代码量增加了,但是开放接口同时也降低了使用者复杂度,因为不这么弄的话,使用者一调用对象,看到一大堆的变量和方法,眼都看花了!
class Student:
def __init__(self, province, school):
self.__province = province # rename为_Student.__province
self.__school = school
def get_info(self):
return f"""省份:{self.__province}\n学校:{self.__school}"""
def set_info(self, province, school):
self.__province = province
self.__school = school
stu1 = Student('Shanghai', 'Linux')
print(stu1.get_info())
stu1.set_info('GuangDong', 'Python')
print(stu1.get_info())
3、property
property是一个装饰器,可以将类中的函数伪装成对象的数据属性,对象访问该属性时触发函数运行并返回执行结果而不用像以前一样加括号!需要注意的是:函数名必须得一样!!!
class Student:
def __init__(self, name):
self.__name = name
@property # 函数伪装成变量名
def student_info(self):
return f'姓名:{self.__name}'
@student_info.setter # 伪装成变量赋值
def student_info(self, name):
self.__name = name
@student_info.deleter # 伪装成删除变量
def student_info(self):
return print('删什么删')
stu1 = Student('sanxi')
print(stu1.student_info)
stu1.student_info = 'chrystal'
print(stu1.student_info)
del stu1.student_info
# 执行得到结果
姓名:sanxi
姓名:chrystal
删什么删