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

这篇具有很好参考价值的文章主要介绍了030.Python面向对象_类&补充_只读属性。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

030.Python面向对象_类&补充_只读属性,Python零基础入门,pycharm,python,PyQt5,py

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

030.Python面向对象_类&补充_只读属性,Python零基础入门,pycharm,python,PyQt5,py
文章来源地址https://www.toymoban.com/news/detail-730338.html

只读属性

概念

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

应用场景

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

实现方法

方式一:使用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}
    
  • 通过示例可以看出来,在经典类中,虽然我们可以定义装饰属性赋值操作的方法,但是并不能真正的将这个操作方法与赋值操作进行关联

到了这里,关于030.Python面向对象_类&补充_只读属性的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 两小时快速入门 TypeScript 基础(二)面向对象

    两小时快速入门 TypeScript 基础(二)面向对象

    个人简介 👀 个人主页: 前端杂货铺 🙋‍♂️ 学习方向: 主攻前端方向,也会涉及到服务端(Node.js 等) 📃 个人状态: 2023届本科毕业生,已拿多个前端 offer(秋招) 🚀 未来打算: 为中国的工业软件事业效力 n 年 🥇 推荐学习:🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2/

    2024年02月12日
    浏览(8)
  • java基础入门-05-【面向对象进阶(static&继承)】

    java基础入门-05-【面向对象进阶(static&继承)】

    类的定义格式如下: 例如: 例如: 1.3.1 封装的步骤 1.使用 private 来修饰成员变量。 2.使用 public 修饰getter和setter方法。 1.3.2 封装的步骤实现 private修饰成员变量 public修饰getter和setter方法 1.4.1 构造方法的作用 在创建对象的时候,给成员变量进行初始化。 初始化即赋值的意

    2024年02月03日
    浏览(13)
  • C++面向对象程序设计-基础入门(超详细)

    C++面向对象程序设计-基础入门(超详细)

    目录 一、c++概述 二、初识c++ 1、第一个c++程序  2、c++面向对象的三大特性(重要) 三、作用域运算符:: 1、使用namespace创建一个命名空间 2、命名空间只能定义在全局 3、 命名空间嵌套  4、随时将新的成员加入命名空间 5、命名空间中 函数的声明和实现分开   6、

    2024年02月16日
    浏览(11)
  • Python基础之面向对象:8、面向对象之元类

    目录 面向对象之元类 一、什么是元类 二、元类推导流程 三、创建类的方式 方式一: 方式二: 四、元类定制类的产生行为 五、元类定制对象的产生行为 六、元类之双下new Python中一切皆为对象,对象是有类实例化生成; 类也是对象(类对象),生成类对象的类可称之为元

    2024年01月20日
    浏览(14)
  • 【Java零基础入门篇】第 ③ 期 - 面向对象编程(二)

    【Java零基础入门篇】第 ③ 期 - 面向对象编程(二)

    博主:命运之光 专栏:Java零基础入门 学习目标 理解面向对象三大主要特征; 掌握类与对象的区别与使用; 掌握类中构造方法以及构造方法重载的概念及使用; 掌握包的定义、包的作用等; 掌握方法的参数传递规则。 什么是封装? 本意是把物体打包装到箱子里,然后封起

    2024年02月04日
    浏览(26)
  • 【Java零基础入门篇】第 ③ 期 - 面向对象编程(一)

    【Java零基础入门篇】第 ③ 期 - 面向对象编程(一)

    博主:命运之光 专栏:Java零基础入门 理解面向对象三大主要特征; 掌握类与对象的区别与使用; 掌握类中构造方法以及构造方法重载的概念及使用; 掌握包的定义、包的作用等; 掌握方法的参数传递规则。 方法的定义 🍓🍓方法在很多地方被称为 函数 (在Java中英文单

    2024年02月04日
    浏览(9)
  • 〖大前端 - 基础入门三大核心之JS篇(58)〗- 面向对象案例

    〖大前端 - 基础入门三大核心之JS篇(58)〗- 面向对象案例

    说明:该文属于 大前端全栈架构白宝书专栏, 目前阶段免费 , 如需要项目实战或者是体系化资源,文末名片加V! 作者:哈哥撩编程,十余年工作经验, 从事过全栈研发、产品经理等工作,目前在公司担任研发部门CTO。 荣誉: 2022年度博客之星Top4、2023年度超级个体得主、谷

    2024年02月03日
    浏览(14)
  • 【Java入门】-- Java基础详解之 [Java面向对象编程(初级)]

    【Java入门】-- Java基础详解之 [Java面向对象编程(初级)]

    目录 1.类与对象 2.类与对象的区别与联系 3.对象在JVM内存中的存在形式(重要) 4.属性/成员变量/字段 5.如何创建对象 6.类和对象的内存分配机制 7.面向对象的三大特征? 8.面向对象和面向过程? 9.匿名对象 10.方法(method) 11.方法的重载(overload) 12.可变形参 13.递归 14.封装 15.四种访

    2024年02月12日
    浏览(13)
  • 【python基础语法十】面向对象

    对类中成员属性和方法的保护,控制外界对内部成员的访问,修改,删除等操作 对象的操作 类的操作 如何在类外访问私有成员 使用类对象删除相应的成员 单继承 多继承 菱形继承 (钻石继承) 内置函数 issubclass 与 isinstance issubclass 判断类的子父关系(应用在类与类之间) isinstance 判

    2024年02月02日
    浏览(17)
  • 【python】08.面向对象编程基础

    【python】08.面向对象编程基础

    活在当下的程序员应该都听过\\\"面向对象编程\\\"一词,也经常有人问能不能用一句话解释下什么是\\\"面向对象编程\\\",我们先来看看比较正式的说法。 \\\"把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为类(class),通过类的封装(encapsulation)隐藏内部

    2024年01月20日
    浏览(15)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包