zoukankan      html  css  js  c++  java
  • 面对对象的。 封装 property

    封装的定义

    封装是面向对象三大特性最核心的一个特性

    封装就是将一段数据与功能打包并且封口,通过封装能控制接口

    封装<========>整合

    接口隐藏的方法

    在类中的属性名前加__前缀,就会实现一个对外隐藏属性效果

     注:隐藏本质是变形

    加__前缀后可以使属性对外隐藏,但是其实本质上是

    class Foo:
        __x = 1  # _Foo__x     在类定义阶段前检测语法时将双下划线开头的属性__x转换成_Foo__x的形式(_类名__属性名)
    
        def __f1(self):  # _Foo__f1   
            print('from test')
    
    
    print(Foo.__dict__)
    print(Foo._Foo__x)
    print(Foo._Foo__f1)
    
    
    导致在类外部无法直接访问双下滑线开头的属性__x,但知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如Foo._A__N,
    所以说这种操作并没有严格意义上地限制外部访问,仅仅只是一种语法意义上的变形。
    

      

    隐藏只对外

    class Foo:
        __x = 1  # _Foo__x = 1       这种隐藏对外不对内,因为__开头的属性会在检查类体代码语法时统一发生变形,
    
        def __f1(self):  # _Foo__f1    每处都变形为一个形式
            print('from test')
    
        def f2(self):
            print(self.__x) # print(self._Foo__x)
            print(self.__f1) # print(self._Foo__f1)
    
    print(Foo.__x)
    print(Foo.__f1)
    obj=Foo()
    obj.f2()
    

      

    class Foo:
        __x = 1  # _Foo__x = 1
    
        def __f1(self):  # _Foo__f1
            print('from test')
    
        def f2(self):
            print(self.__x) # print(self._Foo__x)
            print(self.__f1) # print(self._Foo__f1)
    
    Foo.__y=3
    print(Foo.__dict__)
    print(Foo.__y)
    
    class Foo:
        __x = 1  # _Foo__x = 1
    
        def __init__(self,name,age):
            self.__name=name
            self.__age=age
    
    obj=Foo('egon',18)
    print(obj.__dict__)
    print(obj.name,obj.age)


    变形操作只会在检查类体语法的时候(定义前)发生一次,在此之后定义的__开头的属性都不会变形

      

    隐藏的作用

    定义出来还隐藏不是为了定义不了的,最后还是需要用的的。

    • 控制接口的输入输出

    # 设计者:
    class People:
        def __init__(self, name):
            self.__name = name
    
        def get_name(self):
            # 通过该接口就可以间接地访问到名字属性
            print(self.__name)
    
        def set_name(self,val):
            if type(val) is not str:
                print('必须传字符串类型')
                return
            self.__name=val
    
    # 使用者:
    obj = People('egon')
    # print(obj.name)    # 无法直接用名字属性
    # obj.name = 'EGON'  # 无法直接更改隐藏的属性
    obj.set_name("哈哈")
    obj.get_name()
    
    隐藏数据属性(将数据隐藏起来)就限制了类外部对数据的直接操作,然后类内应该提供相应的接口来允许类外部间接地操作数据,接口之上可以附加额外的逻辑来对数据的操作进行严格地控制
    

      

    隔离复杂度:

    • 隐藏数据属性(将数据隐藏起来)可以明显区分显式的属性与隐式的属性
    • 以此来区分用户可用的属性 与 用户不可用的属性
    • 只为用户显示可用属性,降低用户界面的复杂度

    property

    • 装饰器是在不修改被装饰对象源代码以及调用方式的前提下为被装饰对象添加新功能的可调用对象

      property是一个装饰器,是用来绑定给对象的方法伪造成一个数据属性、
      
      
      # 案例1
      class People:
          def __init__(self, name, weight, height):
              self.name = name
              self.weight = weight
              self.height = height
      
          # 定义函数的原因1:
          # 1、从bmi的公式上看,bmi应该是触发功能计算得到的
          # 2、bmi是随着身高、体重的变化而动态变化的,不是一个固定的值
          #    说白了,每次都是需要临时计算得到的
      
          # 但是bmi听起来更像是一个数据属性,而非功能
          @property
          def bmi(self):
              return self.weight / (self.height ** 2)
          
      obj1 = People('umi', 62.5, 1.8)
      # print(obj1.bmi())
      print(obj1.bmi)
      obj1.height=1.86
      # print(obj1.bmi())
      print(obj1.bmi)
      
      # 案例2
      class People:
          def __init__(self, name):
              self.__name = name
      
          def get_name(self):
              return self.__name
      
          def set_name(self, val):
              if type(val) is not str:
                  print('必须传入str类型')
                  return
              self.__name = val
      
          def del_name(self):
              print('不让删除')
              # del self.__name
      
          name=property(get_name, set_name, del_name)
      
      obj1=People('egon')
      # print(obj1.get_name())
      # obj1.set_name('EGON')
      # print(obj1.get_name())
      # obj1.del_name()
      
      # 人正常的思维逻辑
      print(obj1.name)
      obj1.name=18
      del obj1.name
      
      # 案例3(推荐)
      class People:
          def __init__(self, name):
              self.__name = name
      
      
          @property
          def name(self): # obj1.name
              return self.__name
      
          @name.setter
          def name(self, val): # obj1.name='EGON'
              if type(val) is not str:
                  print('必须传入str类型')
                  return
              self.__name = val
      
          @name.deleter
          def name(self): # del obj1.name
              print('不让删除')
              # del self.__name
              
      obj1=People('egon')
      # 人正常的思维逻辑
      print(obj1.name)
      obj1.name= 'EGON'
      print(obj1.name)
      del obj1.name
      

        

  • 相关阅读:
    requests访问https网站
    BurpSuite中的安全测试插件推荐
    requests.exceptions.SSLError: hostname '127.0.0.1' doesn't match None
    Flask如何使用https?
    sonar如何添加自定义JAVA规则
    如何破解linux用户帐号密码一
    linux下编译运行C程序
    sp_Msforeachtable与sp_Msforeachdb详解
    sp_MSforeachtable使用方法
    SQL Server 存储过程
  • 原文地址:https://www.cnblogs.com/Tornadoes-Destroy-Parking-Lots/p/12662632.html
Copyright © 2011-2022 走看看