12我的python学习之路--面向对象二特殊方法及封装

1. 特殊方法

  • 1.1 引入特殊方法的原因:
    • 在进行对象实例化的过程中,对象的调用者往往很容易遗漏一些操作,导致调用者在使用对象方法时出现程序错误。针对这个问题,Python在实例化对象后,专门对对象内部数据做一些初始化操作,这些操作的打包就叫特殊方法,由对象自动调用,无序人工干预。
  • 1.2 双下划线开头 双下划线结尾
    • 例如:__ init __(self,…) … 传入参数
    • 示例:
      class Person():
      	# init 方法用来初始化某个对象的属性
          def __init__(self,name):
              print('我正在执行init方法....')
              self.name = name
      
          def p(self):
              print(f"Hello, 我是你{self.name}")
      
      p1 = Person('爸爸')
      p1.p()
      p2 = Person('妈妈')
      p2.p()
      
    • 运行结果:
      在这里插入图片描述
  • 1.3 特殊方法不需要我们自己调用,特定的时候自己调用
    • 例如:__ init __ 方法是在初始化实例对象后立即调用 ,请看上图中的提示"我正在执行init方法",代码并没有手动调用init方法。

2. 封装

  • 2.1 出现封装的原因是我们就需要一种方法来增强数据的安全性
    • 属性不能随意修改(这里指隐藏属性名字,同时为修改和访问属性提供接口方法)
    • 属性不能改为任意的值(这里指修改属性时要对值条件检查)
    • 示例:
      class Car():
      
          def __init__(self,name,color,speed):
              self.name = name
              self.color = color
              self.speed = speed
      
          def inst(self):
              print(f'{self.name}汽车是{self.color}...')
      
          def run(self):
              print(f'{self.name}的速度是{self.speed} km/s')
      
      c = Car('奥迪','黑色',3000)
      c.inst()
      c.run()
      # name 虽然被封装了,但仍可通过 对象.属性名 的方式修改。
      # 封装并不是真的把属性隐藏所有人都看不到,这只是一种对象的安全访问机制
      c.name = '宝马'  
      c.inst()
      c.run()
      
    • 运行结果:
      在这里插入图片描述
  • 2.2 封装:隐藏对象中一些不希望被外部访问到的属性或方法,它是面向对象的三大特性之一。
    • getter() 可以访问对象属性
    • setter() 可以修改对象属性
      class Boy:
          def __init__(self, name, age, love):
              self.hiddem_name = name
              self.hiddem_age = age
              self.hiddem_love = love
      
          def description(self):
              print(f'我叫{self.hiddem_name},今年{self.hiddem_age}岁,爱好{self.hiddem_love}')
      
          def get_love(self):
              return self.hiddem_love
      
          def set_love(self,love):
              if isinstance(love,str):  # 必须是字符串类型
                  self.hiddem_love = love
      
          def get_age(self):
              return self.hiddem_age
      
          def set_age(self,age):
              if 0 < age <= 100:
                  self.hiddem_age = age
      
      
      d = Boy("小明",5,'足球')
      d.description()
      d.set_age(10)
      # 通过方法修改爱好
      d.set_love('王者荣耀')   
      d.description()
      # 参数检测 :love = 10 ,非字符串
      d.set_love(10)   
      d.description()
      # 这种方式并没有修改对象中的hiddem_name
      d.name = '小强'
      d.description()
      # 直接修改对象内部变量,成功修改。可知通过改变对象内部的属性名也可提高数据安全
      # 但这种方式不彻底,请看下例中更为高级的用法
      d.hiddem_name = '小李'
      d.description()
      # 获得小李的年龄
      print(d.get_age())
      d.set_love('吃吃吃')
      # 获得小李的爱好
      print(d.get_love())
      
    • 运行结果:
      在这里插入图片描述
    • 小结:封装在保护数据安全的同时,我们虽然不知对象的内部属性细节,但python友好的允许我们使用对象提供的一些方法去操作控制对象,如下图所示:
      在这里插入图片描述
  • 2.3 封装的优势:使用后,确实增加了类的定义的复杂程度,但是也确保了数据的安全性
    • 隐藏属性名,调用者就无法看到对象内部定义的属性名了
    • 增加了getter()和setter()方法,很好控制属性是否只读
    • 使用setter()设置属性,可以增加判断传入的参数是否合法
    • 使用getter()获取属性,使用setter()设置属性可以在读取属性和修改属性的同时做一些其他的处理
  • 2.4 使用双下划线开头来对对象属性进行封装,双下划线开头的属性,是对象的隐藏属性。它只能在类内访问,不可通过对象.属性名 直接访问,但可使用_类名__ 属性名 的方式访问,那么这种封装的方式其实就是给属性起了另外的一个名字。例如 __name --> _ Persom __ name
    • 示例:
      class Person():
          def __init__(self, name):
              self.__name = name
      
          def get_name(self):
              return self.__name
          def set_name(self):
              self.__name = name
      
      p = Person('马云')
      print(p.get_name())
      # 这里对比上例中的hiddem_name 更安全了
      # 双下划线开头,是对象的隐藏属性,该属性只能在类内访问,无法提供对象.属性名访问
      p.__name = '淘宝'
      print(p.get_name())
      # 其隐藏属性只不过将隐藏属性自动改了名字 _类名__属性名,但通过后者还是可以访问对象属性
      p._Person__name = '淘宝'
      print(p.get_name())
      
    • 运行结果:
      在这里插入图片描述
    • 虽然这种方式可以在外部访问,但从封装的角度考虑,我们一般不这样用。
    • 为了书写简便和访问安全,我们一般把 双下划线 改为 单下划线,这样通过_类名__ 属性名 的方式也无法访问对象内部属性。这样书写简单同时,又能保证了数据的安全性,还可以将单下划线开头的属性习惯规定为私有属性,真可谓是一举三得,哈哈。
    • 示例:
      # 该类的内部的所有属性名将双下划线换成单下划线
      class Person():
          def __init__(self, name):
              self._name = name   # 习惯将内部属性名使用单下划线开头
      
          def get_name(self):
              return self._name
          def set_name(self,name):
              self._name = name
      
      p = Person('马云')
      print(p.get_name())
      # 属性名采用单下划线,使得通过双下划线的方式无法修改类内部属性
      p.__name = '淘宝'
      print(p.get_name())
      # 属性名采用单下划线,使得通过 ‘_类__属性名’ 的方式无法修改类内部属性
      p._Person__name = '淘宝'
      print(p.get_name())
      # 以上两种正规的python访问方式都没有将类内属性修改成功,变相的提高了数据的安全性
      # 使用单下划线比双下划线书写简单,虽然通过单下划线方式也可以修改属性,造成数据的不安全
      # 但从数据安全和编程速度的方面综合考虑,选择将单下划线开头定义属性名比以上例子中的方式都好。
      p._name = '淘宝'
      print(p.get_name())
      
    • 运行结果:
      在这里插入图片描述

3. property 装饰器

  • 我们可以使用@property 装饰器来创建只读属性,@property 装饰器会将方法转换为相同名称的只读属性,可以与所定义的属性配合使用,这样可以防止属性被修改。这句话不理解的可以看这儿
  • 使用装饰器后如下例中将 属性名,setter()和getter() 方法名字统一变成属性名。
  • 使用 对象.属性名 一种方式就可完成 setter() 和getter()两种方法,使得面向对象编程更加方便、简单。
  • 对象.属性名 后不再需要括号或括号传参(使用装饰器后加括号()会报错),更加符合初学者的使用习惯,入门比较简单。
  • 示例:
    class Person():
        def __init__(self, name):
            self._name = name
        @property
        def name(self):
            return self._name
        # setter 方法的装饰器 @ 属性名.setter
        @name.setter
        def name(self,name):
            self._name = name
    
    p = Person('马云')
    print(p.name)
    p.name = '马化腾'
    print(p.name)
    
  • 运行结果:
    在这里插入图片描述

4. 总结

  • 通过今天面向对象的学习,我特别想说一些自己以前的经历和感悟。我以前学过C 、C++编程。当学完C的时候,懂得了面向过程的编程方式,它符合人类的思维方式,编写代码容易上手,但代码复用性底,不适合大型程序的开发。当我学C++时,学会了面向对象的编程方式,懂得用更抽象方式类、封装、继承、多态的思想去编写大型的程序,它可以使程序结构清晰,修改维护更加方便,复用性高。当我再用面向对象思想去编写C语言稍大程序时,发现简单容易多了(但遗憾的C没有C++的类、封装、继承等等,即使这样的编程好过面向过程的编程方式),今天呢,我又学到了Python中面向对象的封装技术,发现它比C++的封装技术用的更好(包括特殊方法、隐藏属性、装饰器等),使Python的数据安全性更高和用户编程上更加方便和高效。我想在我以后C++编程上也同样可以用到Python这些高级的编程技巧和思想,任何语言的编程思想都时相通的,我坚信只有这些才是我们真正需要学习并借鉴的,我也为选择学习Python这门语言感到非常高兴!!!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值