Python基础之面向对象:5、三大特征-封装
面向对象之封装
一、封装
1、封装的概念
封装:就是指将数据和功能'封装'起来,封装是一种抽象的概念,封装也就是将某部分数据隐藏起来
2、为什么要封装
封装的主要原因:隔离复杂度(⽐如:电视机,我们看见的就是⼀个⿊匣⼦,其实⾥⾯有很多电器元件,对于⽤户来说,我们不需要清楚⾥⾯都有些元件,电视机把那些电器元件封装在⿊匣⼦⾥,提供给⽤户的只是⼏个按钮接⼝,通过按钮就能实现对电视机的操作
3、封装的两个层面
- 第一个层面:
- 我们创建的类、函数体,本身也是一种封装,想要调用类、函数内的功能和数据,就需要通过类、函数名的方式
- 对于这一层面的封装,类名,函数名就是访问示例的接口
- 第二层面:
- 把类种的功能和数据隐藏起来(可以定义成私有的),无法通过类名的方式直接调用,只能在类中定义一些接口,通过接口的方式访问或修改
二、隐藏与调用的方法
本结说所的封装,是针对封装的第二层面展开所讲
如何将将类中的数据、方法隐藏
Python的class机制采用采用双下划线开头的方式将属性隐藏起来(设置成私有),但这仅仅只是一种变形操作,类中所有双下划线开头的属性都会在定义阶段,检测语法时自动变成'_ 类名 __ 属性名'的形式
1、隐藏的方法
class MyClass:
school_name = '老女孩大学'
'''类在定义阶段 名字前面有两个下划线 那么该名字会被隐藏起来 无法直接访问'''
__age = 18
"""在python中其实没有真正意义上的隐藏 仅仅是换了个名字而已 _类名__名字"""
def __choice_course(self):
print('老北鼻正在选课')
'''
1、加了双下划线的属性,将无法通过对象、类点的方式调用
2、隐藏属性只能在定义阶段使用,后期无法通过添加的方式隐藏
'''
2、调用与修改的方法
在类中的函数体代码时可以直接使用被隐藏的属性的,只需要在类中定义一个函数体代码,在外界调用这个函数体代码时就可以查看被隐藏属性
class Person:
def __init__(self, name, age, hobby):
self.__name = name # 对象也可以拥有隐藏的属性
self.__age = age
self.__hobby = hobby
def get_info(self):
# 类体代码中 是可以直接使用隐藏的名字
print(f"""
姓名:{self.__name}
年龄:{self.__age}
爱好:{self.__hobby}
""")
# 隐藏的属性开放修改的接口 可以自定义很多功能
def set_name(self, new_name):
if len(new_name) == 0:
raise ValueError('你好歹写点东西')
if new_name.isdigit():
raise ValueError('名字不能是数字')
self.__name = new_name
三、伪装
1、伪装的概念
伪装:是指将类中的功能伪装成数据
2、伪装的作用
通常在调用类中的数据时,只需通过点的数据名的方式可以直接调用
将函数伪装成功能后,调用函数时不需要加括号就可调用
3、伪装的实际应用
BMI指数:衡量一个人的体重与身高对健康影响的一个指标
体质指数(BMI)=体重(kg)÷身高^2(m)
EX:70kg÷(1.75×1.75)=22.86
class Person(object):
def __init__(self, name, height, weight):
self.name = name
self.height = height
self.weight = weight
@property
def BMI(self):
return self.weight / (self.height ** 2)
p1 = Person('jason', 1.83, 78)
# p1.BMI() # BMI应该作为人的基本数据而不是方法
# print(p1.BMI) # 利用装饰器伪装成数据
class Foo:
def __init__(self, val):
self.__NAME = val # 将属性隐藏起来
@property
def name(self):
return self.__NAME
@name.setter
def name(self, value):
if not isinstance(value, str): # 在设定值之前进行类型检查
raise TypeError('%s must be str' % value)
self.__NAME = value # 通过类型检查后,将值value存放到真实的位置self.__NAME
@name.deleter
def name(self):
raise PermissionError('Can not delete')
f = Foo('jason')
print(f.name)
f.name = 'jason123'
print(f.name)
del f.name
# f.name = 'jason' # 触发name.setter装饰器对应的函数name(f,’jason')
# f.name = 123 # 触发name.setter对应的的函数name(f,123),抛出异常TypeError
# del f.name # 触发name.deleter对应的函数name(f),抛出异常PermissionError