030.Python面向对象_类补充_只读属性

news2024/12/25 1:47:48

无奋斗不青春

我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈
入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈
虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈
PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)文章合集 👈👈
Oracle数据库教程:👉👉 Oracle数据库文章合集 👈👈
优 质 资 源 下 载 :👉👉 资源下载合集 👈👈

分隔线

类&补充_只读属性

    • 只读属性
      • 概念
      • 应用场景
      • 实现方法
        • 方式一:使用property装饰器
        • 方式二:使用__setattr__方法进行判断
    • 补充_装饰器property详解
      • property作用
      • property源码
      • 补充:经典类和新式类
      • property在两种类中的使用方式
        • property在新式类中的使用方式
        • property在经典类中的使用方式(在Python2.x版本中运行)

只读属性

概念

  • 一个属性(一般指实例属性),只能读取,不能写入

应用场景

  • 有些属性,只限在内部根据不同场景进行修改,对外界来说,不能修改,只能读取

实现方法

方式一:使用property装饰器
  • 步骤
    • 1、通过私有化全部隐藏(既不能读,也不能写)
    • 2、通过方法部分公开(公开读的操作)
  • 示例
    class Person:
        def __init__(self):
            self.__age = 18
    
        def getAge(self):
            return self.__age
    
    
    p = Person()
    
    # print(p.__age)          # 报错,通过属性私有化,隐藏了读操作
    # p.__age = 22            # 并不是修改的私有属性,而是新增了__age属性。通过属性私有化,隐藏了写操作
    
    print(p.getAge())       # 通过指定方法,公开读操作
    
  • 存在问题
    • 1、获取属性的时候需要通过调用方法获取p.getAge(),而不是通过属性获取方式获取p.age
    • 2、在外部直接使用赋值p.age = 22 并不会报错(虽然没有修改内部的私有属性,而是给实例添加了一个age属性,但是给人的感觉就是修改了)
  • 优化
    class Person:
        def __init__(self):
            self.__age = 18
    
        # @property的作用:装饰器,可以使用属性的方式调用这个方法
        @property
        def age(self):
            return self.__age
    
    
    p = Person()
    
    print(p.age)        # 18
    # p.age = 22          # 报错,AttributeError: can't set attribute
    
  • 通过优化之后,就可以通过调用属性的方式调用读属性方法了。并且,外部也不能对这个属性方法进行赋值
  • 缺陷
    • 通过装饰器的方式设置的只读属性,其实还是可以通过 _Person__age 这种改名之后的方式进行修改
    • 也可以通过 实例.__dict__['_Person__age'] = 新值 的方式修改这个只读属性的值
方式二:使用__setattr__方法进行判断
  • 步骤
    • 当通过 实例.属性=值 的方式给实例添加一个属性或修改属性的值时候,会自动调用该方法
    • 在这个方法内部,增加判定方法,满足条件后才把这个属性添加到 __dict__ 这个字典中
  • 代码说明
    class Person(object):
        # 当通过 实例.属性=值 的方式给实例添加一个属性或修改属性的值时候,会自动调用该方法
        # 在这个方法内部,才会真正的把这个属性添加到 __dict__ 这个字典中
        def __setattr__(self, key, value):
            # key:属性   value:属性值
            print(key, value)
    
    
    p = Person()
    p.age = 12          # age 12
    
  • 使用__setattr__设置只读属性
    class Person(object):
        def __init__(self):
            self.__age = 18
            pass
    
        @property
        def age(self):
            return self.__age
    
        # 当通过 实例.属性=值 的方式给实例添加一个属性或修改属性的值时候,会自动调用该方法
        # 在这个方法内部,才会真正的把这个属性添加到 __dict__ 这个字典中
        def __setattr__(self, key, value):
            # key:属性   value:属性值
            # print(key, value)
            if key == 'age':
                print('隐藏属性,不可修改', key)
                return
    
            # self.key = value
            # 不能这么写,这样写也是通过 实例.属性=值 的方式给实例添加一个属性或修改属性的值,会循环调用__setattr__方法,出现死循环
            # 只能通过下面的方法给实例添加/修改属性
            self.__dict__[key] = value
    
    
    p = Person()
    print(p.age)            # 18
    p.age = 22              # 隐藏属性,不可修改 age
    print(p.age)            # 18
    
    
    

补充_装饰器property详解

property作用

  • 将一些“属性的操作方法(删、改、查)”关联到某一个属性中
class Person(object):
    def __init__(self):
        self.__age = 18
    
    @property    
    def age(self, num):
        """属性的操作方法:获取属性值"""
        return self.__age

property源码

  • preoperty源码说明
    class property(object):
        """
        Property attribute.
        
        property(fget=None, fset=None, fdel=None, doc=None) -> property ottribute
        # 调用property函数,传入四个参数,返回一个属性
        # 作用:将一个属性的几个操作方法(删、改、查)关联到返回的这个属性里面
        # 读取这个属性的时候会自动调用第一个参数:fget方法
        # 设置这个属性的值会自动调用第二个参数:fset方法
        # 删除合格属性的时候会自动调用第三个参数:fdel方法
        
          fget
            function to be used for getting an attribute value
            # 用于获取属性值的函数
          fset
            function to be used for setting an attribute value
            # 用于设置属性值的函数
          fdel
            function to be used for del'ing an attribute
            # 用于删除属性值的函数
          doc
            docstring
        
        Typical use is to define a managed attribute x:
        # 典型的用法是定义一个定义和管理一个属性x:
        
        class C(object):
            def getx(self): return self._x
            def setx(self, value): self._x = value
            def delx(self): del self._x
            x = property(getx, setx, delx, "I'm the 'x' property.")
        
        Decorators make defining new properties or modifying existing ones easy:
        # 装饰器使定义新属性或修改现有属性变得容易:
        
        class C(object):
            @property
            def x(self):
                "I am the 'x' property."
                return self._x
                
            # 必须先开启上面的@property装饰器
            @x.setter
            def x(self, value):
                self._x = value
            @x.deleter
            def x(self):
                del self._x
        """
    

补充:经典类和新式类

  • 经典类
    • 概念:没有继承自object的类
  • 新式类
    • 概念:继承自object的类和其派生类
  • 示例
    # 在Python2.x 版本中
    class Person:
        pass
    
    
    class Animal(object):
        pass
    
    
    # 查看基类(父类)
    print(Person.__base__)      # ()
    print(Animal.__base__)      # <class 'object'>
    
    
    # ===================================================
    
    # 在Python3.x 版本中
    class Person:
        pass
    
    
    class Animal(object):
        pass
    
    
    # 查看基类(父类)
    print(Person.__base__)      # <class 'object'>
    print(Animal.__base__)      # <class 'object'>
    
  • 在Python2.x版本中
    • 定义一个类的时候,没有显示的继承自object类,那么这个类就是一个经典类
    • 必须显示的继承自object类,才是一个新式类
  • 在Python3.x版本中
    • 定义一个类的时候,没有显示的继承自pbject类时,会隐式的(默认)继承自object类,这个类就是一个新式类
    • 在通常情况下,我们一般都写成显示继承(即:定义的类继承自object时,也用class Person(object)的方式定义)

property在两种类中的使用方式

property在新式类中的使用方式
  • 使用方式一
    class Person(object):
        def __init__(self):
            # 定义一个属性__age
            self.__age = 18
    
        def get_age(self):
            """定义一个__age属性的操作方法(查)"""
            print('执行get_age方法')
            return self.__age
    
        def set_age(self, num):
            """定义一个__age属性的操作方法(改)"""
            print('执行set_age方法')
            self.__age = num
    
        # 调用property方法,使age属性与get_age、set_age方法进行关联
        # 在获取age属性的值时,自动调用property函数的第一个参数:get_age方法
        # 在设置age属性的值时,自动调用property函数的第二个参数:seg_age方法
        age = property(get_age, set_age)
    
    
    p = Person()
    print(p.age)        # 执行get_age方法  18
    
    p.age = 36          # 执行set_age方法
    print(p.age)        # 执行get_age方法  36
    
    print(p.__dict__)   # {'_Person__age': 36},可以看出来,赋值方式并没有给对象增加新的属性,而是直接修改了原本的属性值
    
  • 使用方式二
    class Person(object):
        def __init__(self):
            self.__age = 18
    
        @property
        def age(self):
            print("执行了@property装饰的age方法")
            return self.__age
    
        @age.setter
        def age(self, num):
            print("执行了@age.setter装饰的age方法")
            self.__age = num
    
        @age.deleter
        def age(self):
            print("执行了@age.deleter装饰的age方法")
            del self.__age
    
    
    
    
    p = Person()
    print(p.age)        # 执行了@property装饰的age方法  18
    
    p.age = 36          # 执行了@age.setter装饰的age方法
    
    print(p.__dict__)   # {'_Person__age': 36}
    
    del p.age           # 执行了@age.deleter装饰的age方法
    
property在经典类中的使用方式(在Python2.x版本中运行)
  • 使用方式一
    # Python2.x版本运行
    # 定义一个经典类,不继承自object类
    class Person:
        def __init__(self):
            self.__age = 18
    
        def get_age(self):
            print '执行了get_age方法'
            return self.__age
    
        def set_age(self, num):
            print '执行了set_age方法'
            self.__age = num
    
        age =property(get_age, set_age)
    
    
    
    p = Person()
    print p.age        # 执行了get_age方法
    
    p.age = 36          # 
    
    print(p.__dict__)   # {'age': 36, '_Person__age': 18}
    
    # 可以看出来,在经典类中,属性的赋值操作并不能关联到property函数的第二个参数
    
  • 使用方式二
    # Python2.x版本运行
    # 定义一个经典类,不继承自object类
    class Person:
        def __init__(self):
            self.__age = 18
    
        @property
        def age(self):
            print '执行了get_age方法'
            return self.__age
    
        @age.setter
        def age(self, num):
            print '执行了set_age方法'
            self.__age = num
    
    
    
    
    p = Person()
    print p.age        # 执行了get_age方法  18
    
    p.age = 36          #
    
    print(p.__dict__)   # {'age': 36, '_Person__age': 18}
    
  • 通过示例可以看出来,在经典类中,虽然我们可以定义装饰属性赋值操作的方法,但是并不能真正的将这个操作方法与赋值操作进行关联

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

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

相关文章

Android NDK开发详解之调试和性能分析的通过Android Studio调试

Android NDK开发详解之调试和性能分析的通过Android Studio调试 启用调试功能在设备上启用调试功能。运行可调试的 build 变体。 更改调试程序类型AutoJavaNative&#xff08;仅适用于 C/C 代码&#xff09;设备支持 run-as。设备启用了 ptrace。 Dual&#xff08;仅适用于 C/C…

电脑录像功能在哪?一文帮你轻松破解

“电脑录像功能在哪里呀&#xff1f;最近因工作上的原因&#xff0c;需要使用电脑来录像&#xff0c;但是找了一上午都找不到在哪里&#xff0c;眼看已经快没时间了&#xff0c;现在真的很急&#xff0c;希望大家帮帮我。” 电脑已经成为了人们生活和工作中必不可少的工具&…

YB4606最大2A电流的可编程过压保护开关IC

概述&#xff1a; YB4606的前端是过电压和过电压电流保护装置。它实现了宽输入电压范围从2.5Voc到40Voc。过电压阈值可以外部编程或设置为内部默认设置。的超低电阻集成电源路径nFET开关确保更好电池充电系统应用性能。它可以提供高达2A的电流&#xff0c;以满足电池供应系统。…

TypeScript之函数以及与JavaScript函数的区别

一、是什么 函数是JavaScript 应用程序的基础&#xff0c;帮助我们实现抽象层、模拟类、信息隐藏和模块 在TypeScript 里&#xff0c;虽然已经支持类、命名空间和模块&#xff0c;但函数仍然是主要定义行为的方式&#xff0c;TypeScript 为 JavaScript 函数添加了额外的功能&…

3.9每日一题(三角函数线性组合求不定积分的特殊方法和一般方法)

方法一&#xff1a;通过特殊方法&#xff1a;加项减项拆凑微分 方法二&#xff1a;用三角函数线性组合不定积分的公式&#xff08;一般方法&#xff09;&#xff1a;

LeetCode字符串题库 之 罗马数字转整数

题目链接&#x1f517;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 1. 题目分析 我们在做题的时候&#xff0c;一定要知道题目的目的是什么&#xff0c;我们可以结合测试用例和提示来看。 我们可以分析以下几点&#xff1a; 1. 每一个罗马数字都…

sql server数据库跟踪——SQL Server Profiler解析

工具&#xff1a; SQL Server Profiler这个工具是SQL Server数据库自带的语句执行跟踪工具&#xff0c;常使用于分析软件修改数据库时所执行的语句&#xff0c;适合用来研究软件运行数据库的原理。 打开方式&#xff1a; 本机安装了SQL server的话&#xff0c;都是自带的。直接…

MySQL中,当update修改数据与原数据相同时会再次执行吗?

一、背景 本文主要测试MySQL执行update语句时&#xff0c;针对与原数据&#xff08;即未修改&#xff09;相同的update语句会在MySQL内部重新执行吗&#xff1f; 二、测试环境 MySQL5.7.25 Centos 7.4 三、binlog_format为ROW 1、参数 2、测试步骤 session1 session2 ses…

优优嗨聚集团:绝味鸭脖市值上升,餐饮业迎来新变革

导语&#xff1a;绝味鸭脖作为中国餐饮行业的领军企业&#xff0c;其市值上升不仅体现了企业的市场价值&#xff0c;更对整个餐饮行业产生了深远的影响。本文将探讨绝味鸭脖市值上升对餐饮行业的影响&#xff0c;以及未来餐饮行业的发展趋势。 一、绝味鸭脖市值上升&#xff0c…

【Docker】Linux路由连接两个不同网段namespace,连接namespace与主机

如果两个namespace处于不同的子网中&#xff0c;那么就不能通过bridge进行连接了&#xff0c;而是需要通过路由器进行三层转发。然而Linux并未像提供虚拟网桥一样也提供一个虚拟路由器设备&#xff0c;原因是Linux自身就具备有路由器功能。 路由器的工作原理是这样的&#xff…

编程实例:农资进销存管理系统软件,支持扫描二维码追溯码

编程实例&#xff1a;农资进销存管理系统软件&#xff0c;支持扫描二维码追溯码 软件支持扫码农资商品的追溯码&#xff0c;二维码。 软件部分功能&#xff1a; 商品信息管理 进货管理 销售管理 库存管理 编程系统化课程总目录及明细&#xff0c;零基础学编程视频教程&…

英码科技成功入选《2023边缘计算产业图谱》两大细分领域

近日&#xff0c;业界知名的边缘计算行业研究机构发布了《2023边缘计算产业图谱》&#xff0c;展示了全球边缘计算产业的最新发展态势和前景。在本次发布的图谱中&#xff0c;英码科技作为边缘计算领域的领先者&#xff0c;成功入选边缘计算一体机和智能终端两大细分领域&#…

钡铼技术X86工控机在控制和通信任务中的优势

X86工控机是一种基于x86架构的工业控制计算机。x86是一种常见的处理器架构&#xff0c;广泛应用于个人电脑和服务器领域。在工业自动化领域&#xff0c;x86架构的处理器和相应的工控机广泛应用于工业控制和监控系统。 x86工控机通常具有以下特点&#xff1a; 处理能力强大&am…

电脑不显示桌面?盘点4个正确操作!

“我的电脑一打开后完全加载不出来桌面&#xff0c;现在我也不知道怎么办&#xff0c;有没有比较了解电脑的大佬可以分享一下经验呀&#xff1f;” 有时候我们使用电脑时可能会遇到桌面上所有的应用程序都消失了甚至桌面不显示的情况。如果电脑不显示桌面我们可能就很难进行下一…

标配率破8成,新能源车2025年全面标配!哪些OTA供应商正在领跑

伴随着汽车智能化的加速渗透&#xff0c;软件在线升级&#xff08;OTA&#xff09;也在快速实现从基于软件层的SOTA &#xff0c;到硬件层的FOTA的全面普及。 其中&#xff0c;在行业内&#xff0c;SOTA普遍是指车辆软件应用层的升级&#xff0c;通过网络将文件从云端服务器下…

众和策略:营收净利双增显韧性 超百亿分红创新高

Choice数据闪现&#xff0c;到10月30日晚8点&#xff0c;沪深北交易所共有5219家A股公司三季报“交卷”。其间&#xff0c;4188家公司盈利&#xff0c;占比八成以上。 消费赛道复苏最为显着&#xff0c;多家上市公司营收、净利润大幅双增&#xff1b;新动力、轿车等赛道亦接连…

MATLAB中perceptron函数用法

目录 语法 说明 示例 使用感知器求解简单分类问题 perceptron函数的功能是简单的单层二类分类器。 语法 perceptron(hardlimitTF,perceptronLF) 说明 注意 Deep Learning Toolbox™ 支持早期形式的感知器。为了获得更好的结果&#xff0c;您应改用 patternnet&#xff0…

影响因素分析玩出新花样,不一样的轨迹模型发一区文章

郑老师统计课程&#xff0c;欢迎点击报名&#xff1a;孟德尔随机化课程即将开班&#xff01;&#xff01; 2023年3月&#xff0c;外国学者在《Age Ageing》&#xff08;一区&#xff0c;IF6.7&#xff09;发表题为&#xff1a;" Eight-year longitudinal falls trajectori…

GameGPT:使用AI实现游戏开发自动化

使用多代理基于AI开发游戏的这种方法果真切实可行吗&#xff1f;如今&#xff0c;从事游戏开发如同走钢丝。游戏行业处于一种怪异的境地&#xff1a;游戏变得越来越酷&#xff0c;越来越有开创性&#xff0c;但同时也变得越来越让人头疼&#xff1a;更大的团队、更长的工作时间…

JVS-BI数字大屏设计器:一站式解决方案

数字大屏介绍 数字大屏是当下数据展示、业务监控、指挥调度常见的业务表达形态&#xff0c;常有可视化的图表、效果装饰、事件操作等技术组成酷炫的效果展示。 配置入口 进入JVS-BI&#xff08;bi.bctools.cn&#xff09;&#xff0c;进入大屏页面&#xff0c;如下图所示 ①…