zoukankan      html  css  js  c++  java
  • 组合, 封装, 访问限制机制, property装饰器, 多态

    组合

    什么是组合

    • 一个对象中的属性是另一个类

    为什么要组合

    • 减少代码冗余并且可以提高程序可扩展性

    如何使用组合

    • 将一个类实例出的对象当做属性添加给另一个类实例出的对象

      class People:
          def __init__(self,name):
              self.name = name
      
      class Date:
          def __init__(self,year,month,day):
              self.year = year
              self.month = month
              self.day = day
      
          def tell_birth(self,obj):
              print(
                  f'''
                  ==={obj.name}的出生日期===
                  年 {self.year}
                  月 {self.month}
                  日 {self.day}
                  '''
              )
      
      class Teacher(People):
          pass
      
      class Student(People):
          pass
      a = Teacher('蔡启龙')
      d = Date(1994,12,10)
      
      a.birth = d
      a.birth.tell_birth(a)
      
      '''
       ===蔡启龙的出生日期===
                  年 1994
                  月 12
                  日 10          
      '''
      

    练习---学生选课系统

    • '''
      选课系统需求:
          1.学生类,老师类, 学生和老师都有课程属性, 每一门课程都是一个对象.
              课程: 课程名字,课程周期,课程价钱
      
          2.学生和老师都有选择课程的功能, 还有打印所有课程的功能.
      '''
      
      class People:
          def __init__(self,name):
              self.name = name
              self.course_lt = []
      
          #选择一门课程的方法
          def choose_course(self,obj):
              self.course_lt.append(obj)
              print(f'{self.name}选择了{obj.course_name}课程')
      
          def prt_course(self):
              print(f'{self.name}的课程信息为:')
              for i in self.course_lt:
                  print(f'''
                  课程名:    {i.course_name}
                  课程周期:  {i.period}
                  课程价格:  {i.price}
                  ''')
      
      class Course:
          def __init__(self,course_name,period,price):
              self.course_name = course_name
              self.period = period
              self.price = price
      
      class Student(People):
          def __init__(self,name,score):
              super().__init__(name)
      
      class Teacher(People):
          def __init__(self,name,level):
              super().__init__(name)
      
      teacher_cql = Teacher('蔡启龙',10)
      stu_tank = Student('tank',0)
      python = Course('python',6,'2万')
      linux = Course('linux',4,1)
      teacher_cql.python = python
      teacher_cql.linux = linux
      
      
      teacher_cql.choose_course(teacher_cql.python)
      teacher_cql.choose_course(teacher_cql.linux)
      teacher_cql.prt_course()
      
      '''
      蔡启龙选择了python课程
      蔡启龙选择了linux课程
      
      蔡启龙的课程信息为:
      
                  课程名:    python
                  课程周期:  6
                  课程价格:  2万
                  
      
                  课程名:    linux
                  课程周期:  4
                  课程价格:  1
      '''
      

    封装

    什么是封装?

    • 比喻
      • 封:比如把一个袋子封起来
      • 装:比如把一堆小猫,小狗,nick装到袋子里
      • 对象就好比一个袋子,袋子里面装一堆属性
    • 封装指的是把一堆属性(特征与技能)封装到一个对象---存
    • 对象可以通过 . 的方式获取属性---取

    为什么要封装?

    • 方便存取,可以通过 对象. 的方式获取属性

    如何封装?

    • 在类内部,定义一堆属性(特征与技能)
    • 特征:变量---数据属性
    • 技能---方法属性
    • 通过 对象.属性 = 属性值 修改属性

    访问限制机制

    什么是访问限制机制?

    • 在类内部定义,凡是以 __ 开头的数据属性与方法属性,都会被python隐藏起来,外部不能直接访问这些属性,比如 __name = 'tank'

    为什么要有访问限制机制?

    • 对重要重要及隐私数据获取的逻辑更加严谨,保证数据的安全性

    怎么实现

    1. 隐私属性通过封装一个接口,在接口内做业务逻辑处理,再把数据返回给调用者.

      class Foo:
          # 数据属性
          __name = 'tank'
      
          # 方法属性
          def __run(self):
              print('running...')
      
          # 获取数据接口
          def get_name(self):
              return self.__name
      
          # 修改属性接口
          def set_name(self):
              self.__name = 'json_sb'
              return self.__name
      
      foo = Foo()
      # print(foo.__name)   #AttributeError: 'Foo' object has no attribute '__name'
      
      res = foo.get_name()  # 获取属性
      print(res)
      
      # print(foo._Foo__name) #强制访问
      
      foo.set_name()  # 修改属性
      print(foo.get_name())  # 获取修改后的属性
      
    2. 在python中不会强制限制属性的访问,类内部使用 __属性名 定义的属性变形成了 _类名__属性名 ,若想直接访问,可以通过 对象.变形后的名字 访问

      class Foo:
          __name = 'tank'	# -->	_Foo__name
      

    练习

    • class Teacher:
          # 初始化对象定制属性
          def __init__(self, name, age, gender):
              self.__name = name
              self.__age = age
              self.__gender = gender
      
          # 打印用户信息接口
          def prt_userinfo(self):
              username = input('请输入用户名:')
              userpwd = input('请输入用户密码:')
              if username == '蔡启龙' and userpwd == '123':
                  print(f'''
      用户信息为:
      姓名: {self.__name}
      年龄: {self.__age}
      性别: {self.__gender}
                  ''')
      
          # 修改用户信息接口
          def change_userinfo(self, name, age, gender):
              if not isinstance(name, str) or not isinstance(age, int) or not isinstance(gender, str):
                  raise TypeError('非法输入!')  # 抛错
              else:
                  self.__name = name
                  self.__age = age
                  self.gender = gender
      
      
      teacher = Teacher('蔡启龙', 18, 'male')  # 实例出一个老师对象
      
      # teacher.prt_userinfo()    #通过打印用户信息接口打印用户信息
      
      teacher.change_userinfo('tank', 19, 'female')  # 通过修改用户信息接口修改用户信息
      
      teacher.prt_userinfo()  # 通过打印用户信息接口打印修改后的用户信息
      
      class ATM:
      
          def __insert_card(self):
              print('插卡...')
      
          def __input_pwd(self):
              print('输入密码...')
      
          def __input_amount(self):
              print('输入金额...')
      
          def __get_money(self):
              print('正在吐钱...')
      
          def __prt_flow(self):
              print('打印账单...')
      
          # 取款接口
          def withdraw(self):
              self.__insert_card()
              self.__input_pwd()
              self.__input_amount()
              self.__get_money()
              self.__prt_flow()
      
      
      atm = ATM()  # 实例化出ATM对象
      
      atm.withdraw()  # 通过取款接口取款,保证取款流程不被修改
      

    property装饰器

    什么是property?

    • python内置的装饰器,主要是给类内部的方法使用

    为什么要用property?

    • 在对象调用某个方法时, 将调用方式从 对象.方法() 变成 对象.方法 ,使方法属性看起来像数据属性

    怎么实现?

    • '''
      计算人体的bmi值: bmi值=体重/(身高**2)
      '''
      
      class People:
          def __init__(self,weight,hight):
              self.weight = weight
              self.hight = hight
      
          #计算bmi值的函数
          @property
          def bmi(self):
              return self.weight/self.hight**2
      
      p = People(60,1.75)
      print(p.bmi)
      # p.bmi = 10  #AttributeError: can't set attribute
      
    • 使用 @property 函数装饰

    • 不能对被装饰的方法进行属性修改

    多态

    什么是多态

    • 面向对象的三大基本特征之一,依赖于继承
    • 一个父类可以有不同的子类
    • 父类中的一个方法,在不同子类中可以有不同执行方式,产生不同的执行结果

    为什么要有多态

    对于不同子类之间存在的差异(多态性),可以在父类中写出通用的抽象方法,做出通用的编程,来适应需求的不断变化

    如何实现?

    1. 子类重用父类的方法并重写该方法来覆盖父类原有的方法

      • class Animal:
            def speak(self):
                print('动物说话...')
        
        class Dog(Animal):
            def speak(self):
                print('狗汪汪汪的说')
        
        class Pig(Animal):
            def speak(self):
                print('猪哼哼哼地说')
        
        class Cat(Animal):
            def speak(self):
                print('猫喵喵喵地说')
        
        dog = Dog()
        pig = Pig()
        cat = Cat()
        
        dog.speak()
        pig.speak()
        cat.speak()
        
    2. 通过抽象类实现---需导入 abc---(abstract class) 模块

      • 抽象类

        • 是什么

          • 一系列类中相同特征与技能的结合体
          • 只能被继承,不能实例化,子类必须实现抽象类中定义的每个抽象方法
        • 为什么

          • 多态的一个表现形式,通过关注抽象类方法的描述而不需要考虑实现细节,有利于协同开发,实现归一化设计
        • 如何实现

          • 导入 abc---(abstract class) 模块

            import abc
            
            class Animal(metaclass=abc.ABCMeta):
                @abc.abstractmethod
                def speak(self):
                    print('动物说话...')
            
                @abc.abstractmethod
                def eat(self):
                    pass
            
            
            class Dog(Animal):
                def speak(self):
                    print('狗汪汪汪的说')
            
                def eat(self):
                    print('狗吃骨头...')
            
                #派生新方法
                def run(self):
                    print('狗奔跑...')
            
            dog = Dog()
            dog.speak()
            dog.eat()
            dog.run()
            
            '''
            没有实现抽象方法时报错:
            Can't instantiate abstract class Dog with abstract methods eat		
            '''
            

    鸭子类型---Duck typing

    美国印第安纳州的诗人的诗句:" When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck."

    什么是鸭子类型

    任何拥有像鸭子一样走和叫方法的对象所属的类型都是鸭子类型,鸭子类型不管制对象的类型,而是关注对象具有的方法

    为什么要有鸭子类型

    多态的一个表现形式,鸭子类型耦合度低,使用鸭子类型可使程序扩展性增强

    如何实现

    既不使用抽象类也不使用继承

    • class Animal:
          def speak(self):
              print('动物说话...')
      
          def eat(self):
              pass
      
      class Dog:
          def speak(self):
              print('狗汪汪汪的说')
      
          def eat(self):
              print('狗吃骨头...')
      

    定义统一接口利用多态性对接口进行多种实现

    • # 例一
      class Animal:
          def speak(self):
              print('动物说话...')
      
      class Dog(Animal):
          def speak(self):
              print('狗汪汪汪的说')
      
      class Pig(Animal):
          def speak(self):
              print('猪哼哼哼地说')
      
      class Cat(Animal):
          def speak(self):
              print('猫喵喵喵地说')
      
      #定义统一接口
      def Bark(obj_animal):
          obj_animal.speak()
      
      dog = Dog()
      pig = Pig()
      cat = Cat()
      
      Bark(dog)
      Bark(pig)
      Bark(cat)
      print('*'*50)
      
      # 例二
      str1 = '1234'
      list1 = [1,2,3]
      
      #类的内置方法
      print(str1.__len__())
      print(list1.__len__())
      print('*'*50)
      
      #内置 "len()" 函数---统一接口
      print(len(str1))
      print(len(list1))
      print('*'*50)
      
      #自定义 "len()" 函数---统一接口
      def my_len(d):
          return d.__len__()
      
      print(my_len(str1))
      print(my_len(list1))
      
  • 相关阅读:
    中文短文本分类
    词袋和词向量模型
    【NLP-2017-SA】翻译-Recurrent Attention Network on Memory for Aspect Sentiment Analysis(2017emnlp)
    过拟合和欠拟合问题总结
    【Docker-6】-Docker删除运行过的镜像
    【Docker-5】-Docker运行自己的镜像
    【Docker-3】-Docker入门命令解读
    【Docker-4】-Docker启动nginx
    【Docker-2】windows下安装docker
    【Docker-1】docker简介
  • 原文地址:https://www.cnblogs.com/-406454833/p/11665805.html
Copyright © 2011-2022 走看看