首页 > 其他分享 >封装

封装

时间:2024-01-05 19:24:20浏览次数:30  
标签:__ .__ 封装 name self print def

(一)封装

(一)封装导读

"""封装导读"""
# 封装其实就是讲属性隐藏起来,不然外界发现和使用
# 接口:可以允许外界使用的内容通过接口开放,让用户通过接口使用

# 封装的原因是:保护隐私,将数据保护起来

# 隐藏属性的发给发是通过__变量名实现的
class Student():
    __school='清华大学'
    def __init__(self,name,age,gender):
        self.__name=name
        self.__age=age
        self.__gender=gender
    def read(self):
        self.__read()
    def __read(self):
        print(f"{self.__name}正在读书")
    #修改名字和属性
    def set_info(self,name,age):
        self.__name=name
        self.__age=age
s1=Student(name='syh',age=23,gender="female")
s1.read()#syh正在读书
print(s1.__dict__)
#{'_Student__name': 'syh', '_Student__age': 23, '_Student__gender': 'female'}

#修改后的s1 字典
s1.set_info(name='su',age=20)
print(s1.__dict__)
#{'_Student__name': 'su', '_Student__age': 20, '_Student__gender': 'female'}

# 如果后续通过对象新增了一个属性,那这个属性和原来封装起来的属性不是同一个了
s1.__school='郑州大学'
print(s1.__school)#郑州大学

(1)什么是封装

  • 在程序设计中,封装(Encapsulation)是对具体对象的一种抽象
    • 即将某些部分隐藏起来,在程序外部看不到,其含义是其他程序无法调用。
    • 要了解封装,离不开“私有化”,就是将类或者是函数中的某些属性限制在某个区域之内,外部无法调用。

(2)为什么要封装

  • 封装数据的主要原因是:保护隐私(把不想别人知道的东西封装起来)

(3)封装的方法

  • 你的身体没有一处不体现着封装的概念:
    • 你的身体把膀胱尿道等等这些尿的功能隐藏了起来,然后为你提供一个尿的接口就可以了(接口就是你的。。。,)
    • 你总不能把膀胱挂在身体外面,上厕所的时候就跟别人炫耀:hi,man,你瞅我的膀胱,看看我是怎么尿的。
  • 电视机本身是一个黑盒子,隐藏了所有细节,但是一定会对外提供了一堆按钮,这些按钮也正是接口的概念,所以说,封装并不是单纯意义的隐藏!!!
  • 快门就是傻瓜相机为傻瓜们提供的方法,该方法将内部复杂的照相功能都隐藏起来了

提示:在编程语言里,对外提供的接口(接口可理解为了一个入口),可以是函数,称为接口函数,这与接口的概念还不一样,接口代表一组接口函数的集合体。

"""封装"""
class Student():
    school='清华大学'
    name='syh'
    age=20
    location='河南省洛阳市'
    _location='河南省洛阳市'
    __location='河南省洛阳市'
    def show_info(self):
        print(self.location)
        print(self._location)
        print(self.__location)
    def _show_info(self):
        print(self.location)
        print(self._location)
        print(self.__location)
    def __show_info(self):
        print(self.location)
        print(self._location)
        print(self.__location)
#实例化得到对象
s1=Student()
#封装数据的属性
print(s1.location)
Student._location
#河南省洛阳市
print(s1._location)
#河南省洛阳市
# print(s1.__location)
#AttributeError: 'Student' object has no attribute '__location'. Did you mean: '_location'?

#封装函数的属性
s1.show_info()
s1._show_info()
# s1.__show_info()
#AttributeError: 'Student' object has no attribute '__show_info'. Did you mean: '_show_info'?

"""总结"""
# 封装数据属性:在类的内部,两个以下的_封装起来的属性,在类的内部可以任意访问,在类的外部(对象)可以访问
# 封装数据属性:在类的内部,两个及以上的_封装起来的属性,在类的内部可以任意访问,但是在类的外部(对象)不可以访问
# 封装函数属性:在类的内部,两个以下封装起来的属性,在类内部可以任意访问,在类外部(对象)可以访问
# 封装函数属性:在类的内部,两个及以上封装起来的属性,在类内部可以任意访问,在类外部(对象)不可以访问

(二)封装之隐藏属性

  • 隐藏数据属性
class Student():
    #将名字和年龄都隐藏起来
    def __init__(self,name,age):
        self.__name=name
        self.__age=age
    # 对外提供访问信息的接口
    def interface(self):
        print(f"姓名:{self.__name},年龄:{self.__age}")
    # 对外设置信息的接口,对信息进行操作
    def set_info(self,name,age):
        if not age.isdigit():
            return "必须是数字"
        self.__name=name
        self.__age=age
# 实例化得到对象
s1=Student(name='syh',age=23)
#查看对象的信息
s1.interface()# 姓名:syh,年龄:23

#调用对象的方法修改对象的信息
s1.set_info(name='su',age='20')
#查看对象的信息
s1.interface()#姓名:su,年龄:20
  • 函数属性
"""函数属性"""
class ATM():
    # 插卡
    def __card(self):
        print("插卡")
    #用户认证
    def __auth(self):
        print("用户认证")
    #输入金额
    def __input(self):
        print("输入金额")
    #取款
    def __get_balance(self):
        print("取款")
    #打印账单
    def __print_bill(self):
        print("打印账单")
    # 主要功能接口
    def main(self):
        self.__card()
        self.__auth()
        self.__input()
        self.__get_balance()
        self.__print_bill()
atm=ATM()
atm.main()
# 插卡
# 用户认证
# 输入金额
# 取款
# 打印账单

(三)封装小结

"""封装小结"""
# 封装可以封装两种属性
# 类中有两种属性:数据属性和函数属性
# 封装的两种属性:数据属性和函数属性

class Student():
    # 封装数据属性
    __school='清华大学'
    # 封装函数属性
    def __read(self):
        print(f"学校名称{self.__school}")
    # 封装是为了保护数据的隐私性
    # 但是我们也需要修改用户隐私数据的需求
    # 所有开放接口来修改隐藏数据
    def set_info(self,school):
        self.__school=school
        self.__read()
#实例化类得到对象
s1=Student()
print(Student.__dict__)
#{'__module__': '__main__', '_Student__school': '清华大学', '_Student__read': <function Student.__read at 0x0000024C47722320>, 'set_info': <function Student.set_info at 0x0000024C47722950>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None}
print(s1._Student__school)# 清华大学
# 调用set_info修改数据
s1.set_info(school='郑州大学')
#学校名称郑州大学
  • 总结隐藏属性与开放接口,本质就是为了明确地区分内外,类内部可以修改封装内的东西而不影响外部调用者的代码;
  • 而类外部只需拿到一个接口,只要接口名、参数不变,则无论设计者如何改变内部实现代码,使用者均无需改变代码。
  • 这就提供一个良好的合作基础,只要接口这个基础约定不变,则代码的修改不足为虑。

(四)property装饰器

(1)什么是property

  • property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值

(2)BMI例子

  • BMI指数是用来衡量一个人的体重与身高对健康影响的一个指标
  • 成人的BMI数值:
    • 过轻:低于18.5
    • 正常:18.5-23.9
    • 过重:24-27
    • 肥胖:28-32
    • 非常肥胖, 高于32
  • 计算公式
    • 体质指数(BMI)=体重(kg)÷身高^2(m)
    • EX:70kg÷(1.75×1.75)=22.86
  • 身高或体重是不断变化的
    • 因而每次想查看BMI值都需要通过计算才能得到,但很明显BMI听起来更像是一个特征而非功能,为此Python专门提供了一个装饰器property
    • 可以将类中的函数“伪装成”对象的数据属性,对象在访问该特殊属性时会触发功能的执行,然后将返回值作为本次访问的结果
class Person():
    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)
p = Person('syh',height=1.8,weight=85)
# 触发bmi正常执行,将p传入到self ,执行后返回值作为本次的结果
# 正常的调用是p。bmi()
# 现在加入property装饰器后,没有加()就调用成功了!
print(p.bmi)#26.234567901234566

(3)为什么要用property

  • 将一个类的函数定义成特性以后,对象再去使用的时候obj.name,根本无法察觉自己的name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则
  • 面向对象的封装有三种方式:
    • 【public】
      • 这种其实就是不封装,是对外公开的
    • 【protected】
      • 这种封装方式对外不公开
      • 但对朋友(friend)或者子类(形象的说法是“儿子”,但我不知道为什么大家 不说“女儿”,就像“parent”本来是“父母”的意思,但中文都是叫“父类”)公开
    • 【private】
      • 这种封装对谁都不公开
  • python并没有在语法上把它们三个内建到自己的class机制中,在C++里一般会将所有的所有的数据都设置为私有的,然后提供set和get方法(接口)去设置和获取,在python中通过property方法可以实现
"""方式一"""
class Student():
    #将数据隐藏起来
    def __init__(self,name1,age):
        self.__name=name1
        self.__age=age

    @property
    def name(self):
        return self.__name
    @name.setter
    def name(self,name1):
        self.__name=name1
    @name.deleter
    def name(self):
        raise PermissionError('Can not delete')


s=Student(name1='syh',age=23)
print(s.name)
# syh
s.name='su'
print(s.name)
# su
del s.name
#PermissionError: Can not delete



"""方式二"""
class Student():

    #将数据隐藏起来
    def __init__(self,name):
        self.__name=name

    # 得到值
    def get_name(self):
        return self.__name
    # 设定值
    def set_name(self,name):
         self.__name=name
    # 删除
    def del_name(self):
        raise PermissionError('Can not delte')

    # 不使用装饰器,而是使用 包装的 形式
    name=property(get_name,set_name,del_name)
s=Student(name='syh')
print(s.name)# syh
# 触发name.setter装饰器对应的函数name(s,'su')
s.name='su'
print(s.name)# su
# 触发name.deleter对应的函数name(f),抛出异常PermissionError
del s.name
#PermissionError: Can not delte

(五)封装和扩展性

  • 封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;
  • 而外部使用用者只知道一个接口(函数),只要接口(函数)名、参数不变,使用者的代码永远无需改变。
  • 这就提供一个良好的合作基础——或者说,只要接口这个基础约定不变,则代码改变不足为虑。

(1)设计者

class Room:
    def __init__(self, name, owner, width, length, high):
        self.name = name
        self.owner = owner
        self.__width = width
        self.__length = length
        self.__high = high

    # 对外提供的接口,隐藏了内部的实现细节,此时我们想求的是面积
    def tell_area(self):  
        return self.__width * self.__length

(2)使用者

class Room:
    def __init__(self, name, owner, width, length, high):
        self.name = name
        self.owner = owner
        self.__width = width
        self.__length = length
        self.__high = high

    # 对外提供的接口,隐藏了内部的实现细节,此时我们想求的是面积
    def tell_area(self):
        return self.__width * self.__length


# 使用者
room = Room('卧室', 'dream', 20, 20, 20)
# 使用者调用接口tell_area
result = room.tell_area()
print(result)
# 400

(3)更好的扩展性

# 类的设计者,轻松的扩展了功能,而类的使用者完全不需要改变自己的代码
class Room:
    def __init__(self, name, owner, width, length, high):
        self.name = name
        self.owner = owner
        self.__width = width
        self.__length = length
        self.__high = high

    # 对外提供的接口,隐藏内部实现,
    # 此时我们想求的是体积,内部逻辑变了,只需求修该下列一行就可以很简答的实现,
    # 而且外部调用感知不到,仍然使用该方法,但是功能已经变了
    def tell_area(self):
        return self.__width * self.__length * self.__high


# 对于仍然在使用tell_area接口的人来说,根本无需改动自己的代码,就可以用上新功能
room = Room('卧室', 'dream', 20, 20, 20)

# 使用者调用接口tell_area
result = room.tell_area()
print(result)
# 8000

标签:__,.__,封装,name,self,print,def
From: https://www.cnblogs.com/suyihang/p/17947891

相关文章

  • 封装、继承、多态
    封装、继承、多态1.封装封装就是将属性隐藏,不让外界发现或使用将可以允许外界使用的内容通过接口开发,让用户通过接口使用隐藏属性的方法是通过__变量名1.1封装之隐藏属性隐藏数据属性classTeacher:def__init__(self,name,age):#将名字和年纪都隐藏......
  • 单调栈分类、封装和总结
    作者推荐map|动态规划|单调栈|LeetCode975:奇偶跳通过枚举最小(最大)值不重复、不遗漏枚举所有子数组C++算法:美丽塔O(n)解法单调栈左右寻找第一个小于maxHeight[i]的left,right,[left,right]直接的高度都是maxHeight[i]可以用封装的类,可以理解为枚举山顶这个子数组【单调栈]LeetCode8......
  • 35 VIVADO用户IP软件总线接口封装
    软件版本:VIVADO2021.1操作系统:WIN1064bit硬件平台:适用XILINXA7/K7/Z7/ZU/KU系列FPGA登录米联客(MiLianKe)FPGA社区-www.uisrc.com观看免费视频课程、在线答疑解惑!1概述使用VIVADO基于图形化创新编程FPGA的方式可以大大提高FPGA编程效率,但是前提是把代码打包成图形化的IP......
  • 【vue】,封装的table组件,table表格超出高度自适应滚动效果,设置页面全局统一自适应高度
    需求背景:为了使后台页面的table列表页面始终保持统一的高度,无论我们的列表数据有多少都只占一个屏幕的高度,如果table表格的数据太多,只滚动table表格的数据,页面高度保持不变;使用window.onresize监听浏览器的高度://tableHeight:为el-table绑定的height高度;onMounted......
  • 34 VIVADO自定义IP简单封装方法
    软件版本:VIVADO2021.1操作系统:WIN1064bit硬件平台:适用XILINXA7/K7/Z7/ZU/KU系列FPGA登录米联客(MiLianKe)FPGA社区-www.uisrc.com观看免费视频课程、在线答疑解惑!1概述XILINX作为FPGA全球老大,不仅仅是硬件技术实力,而且EDA软件也是非常优秀,XILINXVIVADO是业内最先进的开......
  • TS MQTT封装
    TSMQTT封装导入相关包npmimqttnpmilodashguid随机生成就行,具体可以参考百度或者随便生成一个随机数*代码封装importmqttfrom'mqtt'importtype{MqttClient,OnMessageCallback,IClientOptions,IClientPublishOptions,IPublishPacket}from'mqtt'impor......
  • 包&封装&继承总结
    总结包package概念概念:简单的理解包就是一个文件夹。包作用①方便管理项目中的类等文件。②可以避免类名冲突的问题。使用包定义包包命名规范:一般是公司域名反写.项目名.模块名字.子模块名;要求:包名是全英文小写。packagecn.itsource.packagedemo;//声明包导入包......
  • PC9094超小体积封装可编程过流过压保护IC
    概述:PC9094过电压和过电流保护该器件具有低80mΩ(TYP)导通电阻集成MOSFET,主动保护低电压系统的电压供应故障高达+29V直流电。输入电压超过过电压阈值将导致内部MOSFET关闭,防止损坏下游的过大电压设备。过电压保护阈值默认为6V。2.3V/3.6V/11V/16V/23V还有其他版本OVP和无OVP。PC9094......
  • 使用hook封装表格常用功能(react)
    实现内容配置分页:usePagination生成过滤项:useFilter获取表格选择配置:useSelect生成批量删除按钮:useDelete生成模态框:useModal示例render部分:<React.Fragment><Formlayout="inline">{DeleteEle}{FilterEles}</Form><Table{...{......
  • 封装一个表情包组件(支持自定义表情图片)(基于vue3语法)
    效果图文件图直接贴代码emotion.vue<template><divclass="emotion-containerbeauty-scroll-livechat"><divclass="emotion-btn"@click="toggleEmotionShow"><spanclass="iconfonticon-biaoqing1&quo......