面向对象之封装

目录

  • 面向对象之封装
  • 一、封装
  • 1、封装的概念
  • 2、为什么要封装
  • 3、封装的两个层面
  • 二、隐藏与调用的方法
  • 1、隐藏的方法
  • 2、调用与修改的方法
  • 三、伪装
  • 1、伪装的概念
  • 2、伪装的作用
  • 3、伪装的实际应用

一、封装

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