Python 面向对象之封装和装饰器property

news2024/11/28 6:25:32

Python 面向对象之封装和装饰器property

【一】概念

  • 封装是面向对象的三大特征之一
  • 封装:将属性方法包在一起,并对外部提供接口,控制外部对内部数据的访问和修改
  • 封装有助于隐藏对象的内部细节,提供更清晰的结构,提高了代码的安全性可维护性

【二】隐藏属性和方法

【1】概念

  • 类的设计者不想使用者直接访问到属性,就可以将属性进行隐藏,有隐藏属性隐藏方法
  • pythonclass机制采用双下划线开头的方式进行隐藏属性和方法私有属性、私有方法
  • 但是并没有真正意义上的隐藏,隐藏的机制
    • 在类的定义阶段,双下划线开头的属性和方法都会发生变形
    • 属性变形:_类名__属性
    • 方法变形:_类名__方法
    • 类的外部可以通过访问变形可以使用这个私有属性或者方法
    • 然而类的内部是可以通过双下划线访问的,这是因为在检查类体代码语法时统一发生变形类定义阶段
    • 这种变形指在类的定义阶段检查类体语法时发生一次,之后再定义的双下划线开头的属性和方法都不会变形,即可以直接通过双下划线开头访问

【2】代码解释

# 类的设计者不想使用者直接访问到属性,就可以将属性进行隐藏,有隐藏属性和隐藏方法
# python的class机制采用双下划线开头的方式进行隐藏属性和方法(私有属性、私有方法)

class A:
    # 类属性
    name = "bruce"
    # 私有属性(隐藏属性)
    __private_age = 18

    # 实例方法
    def instance_method(self):
        print("这是是实例方法")

    # 私有方法(隐藏方法)
    def __private_method(self):
        print("这是私有方法")

a = A()

# 访问属性
print(a.name)                   # bruce
# print(a.__private_age)        # 报错,访问不到
print(A.name)                   # bruce
# print(A.__private_age)        # 报错,访问不到

# 访问方法
a.instance_method()           # 这是是实例方法
# a.__private_method()        # 报错,访问不到
A.instance_method(a)          # 这是是实例方法
# A.__private_method()        # # 报错,访问不到
# 隐藏的机制:
# 在类的定义阶段,双下划线开头的属性和方法都会发生变形
# 属性变形:_类名__属性
# 方法变形:_类名__方法
# 在类的外部可以通过访问变形,可以使用这个私有属性或者方法
# 然而类的内部是可以通过双下划线访问的,这是因为在检查类体代码语法时统一发生了变形(类定义阶段)
# 这种变形指在类的定义阶段(检查类体语法时)发生一次,之后再定义的双下划线开头的属性和方法都不会变形,即可以直接通过双下划线开头访问
class A:
    name = "bruce"
    __private_age = 18

    # 实例方法
    def instance_method(self):
        print("这是是实例方法")
        # 类内部访问私有属性
        print(f"name:{self.name} age:{self.__private_age}")
        # 类内部访问私有方法
        self.__private_method()
    # 私有方法(隐藏方法)
    def __private_method(self):
        print("这是私有方法")


a = A()

# 类和实例都可以访问不在重复写
# 访问属性
print(a.name)                   # bruce
# 通过变形访问
print(a._A__private_age)        # 18


# 访问方法
a.instance_method()
# 这是是实例方法
# name:bruce age:18
# 通过变形访问
a._A__private_method()
# 这是是实例方法
# name:bruce age:18


# 类外部添加私有属性(并不是私有属性)
a.__private_age = 20
print(a.__private_age)          # 20
print(a._A__private_age)        # 18

【三】开放接口

  • 定义了属性和方法,那么这个属性和方法就一定是有一定的作用的,不能仅仅只是隐藏起来
  • 隐藏不是目的目的是为了更安全更好的使用

【1】隐藏属性

【1】概念
  • 隐藏属性:将属性隐藏起来,限制类外部对数据的直接访问用通过类提供的接口来允许类外部间接访问和操做,接口之上我们可以添加额外的逻辑来对数据进行处理,这样更安全可靠
【2】代码解释
  • 在银行系统中,其中金额是极其重要的数据,所以我们要隐藏这个属性,提供接口给类外部间接操作数据
class AtmUser:
    def __init__(self, name):
        self.username = name
        # 隐藏属性金额
        self.__money = 100

    def withdraw_money(self, money: int):
        # 金额校验
        if type(money) != int:
            print("取款失败:输入非法")
        elif money > self.__money:
            print("取款失败:你没有这么多钱")
        else:
            self.__money -= money
            print(f"取款成功:你还有{self.__money}元")

    def recharge_money(self, money: int):
        # 金额校验
        if type(money) != int:
            print("充值失败:输入非法")
        else:
            self.__money += money
            print(f"充值成功:你还有{self.__money}元")


bruce_atm = AtmUser("bruce")
# 取款
# bruce_atm.money -= 100            # 无法访问私有属性
bruce_atm.withdraw_money(100)  # 取款成功:你还有0元

# 充值
# bruce_atm.money += 100            # 无法访问私有
bruce_atm.recharge_money(100)  # 充值成功:你还有100元

【2】隐藏方法

【1】概念
  • 隐藏方法:目的在于隔离复杂度隐藏内部实现细节
【2】代码解释
  • 同样的在银行系统中,客户的操作有存钱取钱等,银行却需要更多的方法,比如检验你登录或者插卡没有,用户的身份验证、金额的验证等方法,这些方法不需要给客户提供,所以要隐藏这些方法,隔离复杂度
class AtmUser:
    def __init__(self, name):
        self.username = name
        # 隐藏属性金额
        self.__money = 100

    # 隐藏方法
    def __card_check(self):
        print("检查是否插卡")
        pass
    def __check_user_info(self):
        print("检查用户信息")
        pass
    def __money_chcek(self):
        print("检查金额是否满足要求")
        pass

    def withdraw_money(self, money: int):
        # 调用私有方法
        self.__card_check()
        self.__check_user_info()
        self.__money_chcek()
        # 调用私有属性
        self.__money -= 100

【四】装饰器property

  • property是一种特殊的装饰器,用于将类的方法伪装成类的属性
  • 它能够将一个方法伪装成只读属性,使得在访问这个属性时可以像访问普通属性一样实际上还是调用相应的方法

【1】应用场景一:MyDivmod

  • 内置函数divmod中输入被除数除数就可以得到余数
  • 商和余数可以用方法计算得到,但是这两个更像是属性,所以可以用装饰器property装饰成属性
# 定义一个求商取余的类
class MyDivmod:
    def __init__(self, dividend, divisor):
        # 被除数
        self.__dividend = dividend
        # 除数
        self.__divisor = divisor

    # 求商
    @property
    def discuss(self):
        return self.__dividend // self.__divisor

    # 求余数
    @property
    def remainder(self):
        return self.__dividend % self.__divisor

result = MyDivmod(9,4)
print(f"商:{result.discuss}")
print(f"余:{result.remainder}")
# 商:2
# 余:1

【2】应用场景二:装饰器链

  • 私有属性在类里面定义好了,我们希望在类的外部获取它的值、修改他的值和删除这个值,可以使用提供的接口方法,但是我们更想让他像一个普通的属性一样,直接通过.号运算符有进行取值、赋值和删除值
  • 注意:三个方法的名字必须一样,形参可以不通过
  • 注意:三个方法的名字必须一样,形参可以不通过
  • 注意:三个方法的名字必须一样,形参可以不通过
class A:
    __x = "aaa"

    # 在取值的前面只需要使用装饰器property
    @property
    def x(self):
        print("取值方法")
        return self.__x

    # 在赋值方法的前面需要加上取值方法的函数名.setter
    # 这个方法名需要和取值的方法名相同
    @x.setter
    def x(self, value):
        print("赋值方法")
        self.__x = value

    # 在赋值方法的前面需要加上取值方法的函数名.deleter
    # 这个方法名需要和取值的方法名相同
    @x.deleter
    def x(self):
        print("删除值方法")
        del self.__x


a = A()

print(a.x)      # 取值方法
# aaa
a.x = "bb"      # 赋值方法
del a.x         # 删除值方法

【3】应用场景三:经典的属性定义方式

  • 在场景二中每个取值赋值删除值的方法前面都需要添加装饰器property对应的内容
  • 为了简化代码,我们可以使用property()函数来创建一个属性并将相应的取值、赋值和删除值的方法传递给它
  • 注意:三个方法的名字不能相同,形参可以不同,传入property函数默认是位置传参
  • 注意:三个方法的名字不能相同,形参可以不同,传入property函数默认是位置传参
  • 注意:三个方法的名字不能相同,形参可以不同,传入property函数默认是位置传参
class A:
    __x = "aaa"

    # 取值方法
    def get_x(self):
        print("取值方法")
        return self.__x


    # 赋值方法
    def set_x(self, value):
        print("赋值方法")
        self.__x = value

    # 删除值方法
    def del_x(self):
        print("删除值方法")
        del self.__x

    # 使用property函数创建这个属性
    # 不用self.传入,直接传入地址
    # 位置传参(取值方法地址、赋值方法地址、删除值方法地址)
    x = property(get_x, set_x, del_x)


a = A()

print(a.x)      # 取值方法
# aaa
a.x = "bb"      # 赋值方法
del a.x         # 删除值方法

【五】总结

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1356935.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年终总结(脚踏实地,仰望星空)

回忆录 2023年,经历非常多的大事情,找工作、实习、研究生毕业、堂哥结婚、大姐买车、申博、读博、参加马拉松,有幸这一年全家人平平安安,在稳步前进。算是折腾的一年,杭州、赣州、武汉、澳门、珠海、遵义来回跑。完成…

安全狗入选“2023年福建省信息技术应用创新解决方案”名单

近日,福建省数字福建建设领导小组办公室公布了2023年福建省信息技术应用创新解决方案入选项目名单。 作为国内云原生安全领导厂商,安全狗凭借综合且具备突出创新水平的方案入选。 据悉,此次方案征集面向全省信创企业和用户单位,…

【Linux】——基本指令(二)

💗个人主页💗 ⭐个人专栏——数据结构学习⭐ 💫点击关注🤩一起学习C语言💯💫 目录 导读:1. vim 指令2. head指令3. tail指令4. tree指令5. 输出重定向6. echo指令7. wc指令8. | 字符9. date指令…

炼石免改造加密亮相2023商密大会,参编密评行业报告发布

2023年8月9-11日,2023商用密码大会在河南省郑州国际会展中心圆满召开,是我国商密领域规格最高、规模最大、影响最广的全国性商用密码盛会,也是《密码法》和新修订的《商用密码管理条例》正式实施以来的第一次全国性的盛会。大会以“密码赋能美…

51、全连接 - 特征的全局融合

Resnet50 中的核心算法,除了卷积、池化、bn、relu之外,在最后一层还有一个全连接。 下图是 Resnet50 网络结构结尾的部分,最后一层 Gemm(通用矩阵乘法)实现的就是全连接操作。而矩阵乘法我们之前介绍过,传送门在:矩阵乘。 卷积也好,矩阵乘法也好,其目的都是为了完成神…

Ajax基础入门_Ajax概述,同步与异步,Axios的使用,JSON数据及FastJSON的使用

Ajax 文章目录 Ajax1 概述2 作用3 同步和异步3.1 同步3.2 异步 4 代码编写4.1 服务端4.2 客户端 5 Axios5.1 使用5.2 代码5.2.1 前端5.2.2 后端 5.3 请求方法别名 6 JSON6.1 概述6.2 JSON 基础语法6.2.1 定义格式6.2.2 js 对象与JSON的转换 6.3 发送异步请求携带参数6.4 JSON串…

高分青海中心完成积石山6.2级地震(青海区域)卫星遥感数据与技术支撑工作

2023年12月18日23时59分,甘肃临夏州积石山县发生6.2级地震,青海省部分地区有明显震感,海东市民和县、化隆县、循化县出现不同程度人员伤亡和房屋受损情况。地震发生后,高分青海中心在国家航天局对地观测与数据中心的大力支持与紧急…

羊大师讲解,中国羊奶文化的丰富渊源

羊大师讲解,中国羊奶文化的丰富渊源 中国羊奶文化源远流长,几千年来与中华民族的生活息息相关。自古以来,中国人民就以羊为重要的家畜之一,不仅用于养殖和农业生产,更体现了中国人民的饮食文化和生活方式。中国羊奶文…

2分钟了解什么是socket?

文章目录 概念比喻类型Socket 与 TCP、UDP的关系 概念 Socket 是提供网络通信功能的编程接口(API),提供了网络通信的基本操作,允许程序或进程之间进行数据交换。是传输层协议的具体软件实现,它封装了协议底层的复杂实…

mysql死锁排查

查看正在进行中的事务 SELECT * FROM information_schema.INNODB_TRX;字段解释trx_id唯一事务id号,只读事务和非锁事务是不会创建id的trx_state事务的执行状态,值一般分为:RUNNING, LOCK WAIT, ROLLING BACK, and COMMITTING.trx_started事务…

基于Java SSM框架实现中国古诗词学习平台项目【项目源码】

基于java的SSM框架实现中国古诗词学习平台系统演示 JSP技术介绍 JSP技术本身是一种脚本语言,但它的功能是十分强大的,因为它可以使用所有的JAVA类。当它与JavaBeans 类进行结合时,它可以使显示逻辑和内容分开,这就极大的方便了用…

LabVIEW开发分布式光纤油气管道泄漏检测及预警系统

LabVIEW开发分布式光纤油气管道泄漏检测及预警系统 随着油气工业的发展,管道泄漏成为一个严峻的安全问题。本文介绍了一种基于LabVIEW的分布式光纤油气管道泄漏检测及预警系统的设计思路和组成结构。系统包括硬件和软件两部分,其中硬件部分详细阐述了分…

进程的介绍及相关命令

首先,先了解一下计算机五大性能的命令 cpu top w 内存 top free 硬盘剩余 df 硬盘读写性能 iostat 网络带宽 iftop 一,进程与程序 1,什么是程序 : 硬盘上躺着,执行特点任务的一串代码 2&am…

AI边缘计算智能分析网关V4如何配置周界入侵检测算法

旭帆科技的智能分析网关V4内含近40种智能分析算法,包括人体、车辆、消防、环境卫生、异常检测等等,在消防安全、生产安全、行为检测等场景应用十分广泛,如常见的智慧工地、智慧校园、智慧景区、智慧城管等等,还支持抓拍、记录、告…

动态分区分配算法-第四十四天

目录 前言 首次适应算法(First Fit) 最佳适应算法(Best Fit) 最坏适应算法(Worst Fit) 临近适应算法(Next Fit) 本节思维导图 前言 动态分区分配算法:在动态分区分…

C#使用switch多路选择语句判断何为季节

目录 一、 switch语句 二、示例 三、生成 一、 switch语句 switch语句是多路选择语句,它通过一个表达式的值来使程序从多个分支中选取一个用于执行的分支。 switch表达式的值只可以是整型、字符串、枚举和布尔类型。 switch语句中多个case可以使用一个break。 在…

移动通信原理与关键技术学习(2)

1.多径信道滤波器表示,多径信道可以认为是线性时变滤波器,接收信号为发送信号与信道冲激响应的卷积。 2.调制就是对信号源的信息进行处理加到载波上,使其变为适合于信道传输的形式的过程,就是使载波随信号而改变的技术。 3.进行调…

CodeWave智能开发平台--03--目标:应用创建--01模板创建依赖问题修改

摘要 本文是网易数帆CodeWave智能开发平台系列的第03篇,主要介绍了基于CodeWave平台文档的新手入门进行学习,实现一个完整的应用,本文主要完成模板创建时的依赖问题解决。 CodeWave智能开发平台的03次接触 CodeWave参考资源 网易数帆Code…

3个.NET开源简单易用的任务调度框架

前言 今天分享3个.NET开源、简单、易用的任务调度框架,帮助大家在做定时任务调度框架技术选型的时候有一个参考。 Quartz.Net Quartz.NET是一个功能齐全的开源作业调度系统,可用于从最小的应用程序到大规模企业系统。 Quartz.NetUI Quartz.NetUI是一…

Java 泛型深入解析

Java 中的泛型是一种强大的编程特性,允许我们编写更加通用和类型安全的代码。本篇博客将深入探讨 Java 泛型的各个方面,包括泛型类、泛型方法、泛型接口以及泛型通配符。 1. 泛型类 首先,让我们看一个简单的泛型类的例子。在下面的代码中&a…