zoukankan      html  css  js  c++  java
  • 【0828 | Day 25】类的组合/多态与多态性/封装

    组合

    一、什么是组合

    对象的某个属性是另外定义的一个类的对象

    #举个栗子
    class Animal:
    	def __init__(self, level):
            self.level = level
            
    class Level:
            pass
        
    #Animal类的属性level是另一个类的对象
    level = Level()
    l = Animal(level) 
    

    二、为什么使用组合

    • 减少代码冗余

      class Person:
          school = 'oldboy'
      
      class Teacher(Person):
          def __init__(self,name,age,level,course):
              self.name = name
              self.age = age
              self.level = level
              #course是课程对象,表示老师教授的课程
              self.course = course
      
      class Student(Person):
          def __init__(self,name,age,course):
              self.name = name
              self.age = age
              # course是课程对象,表示学生选的课程
              self.course = course
      
      class Course:
          def __init__(self,course_name,course_price,course_period):
              self.name = course_name
              self.price = course_price
              self.period = course_period
      
              
      course=Course('Python', 20000, 6)
      stu=Student('nick', 19, course)
      teacher=Teacher('nick', 19, '高级', course)
      
      #查看老师教授的课程名
      print(teacher.course.name)  #Python
      

    三、如何使用组合

    class Person:
        school = 'oldboy'
        
    class Teacher(Person):
        def __init__(self, name, age, level, course):
            self.name = name
            self.age = age
            self.level = level
            #course是课程对象,表示老师教授的课程
            self.course = course
    
    class Student(Person):
        # course=[]  #错误
        def __init__(self, name, age):
            self.name = name
            self.age = age
            # course是课程对象,表示学生选的课程
            self.course_list = []
        def choose_course(self, course):
            # self.course=[]  #错误
            #把课程对象追加到学生选课的列表中
            self.course_list.append(course)
    
        def tell_all_course(self):
            #循环学生选课列表,每次拿出一个课程对象
            for course in self.course_list:
                #课程对象.name  取到课程名字
                print(course.name)
    
    class Course:
        def __init__(self,course_name,course_price,course_period):
            self.name = course_name
            self.price = course_price
            self.period = course_period
    
    
    
    course = Course('Python',20199,7)
    stu1 = Student('nick',19)
    stu1.choose_course(course)
    stu2 = Student('王二丫',19)
    stu2.choose_course(course)
    stu2.choose_course(Course('linux',19999,5))
    
    
    #查看stu1选的所有课程名称
    #方式一(通过普通函数)
     def tell_all_course(student):
         for course in student.course_list:
            print(course.name)
    
    tell_all_course(stu1)
    tell_all_course(stu2)
    
    #方式二(通过对象的绑定方法)
    stu1.tell_all_course()
    stu2.tell_all_course()
    

    多态和多态性

    一、什么是多态

    表示一类事物具有多种形态,例如class Animal,这个Animal类里又分为人、猪、猫等等

    二、什么是多态性

    表示向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为(即方法)

    class Animal:
        def run(self):  # 子类约定俗称的必须实现这个方法  #def click(self):....等
            raise AttributeError('子类必须实现这个方法')
    
    
    class People(Animal):
        def run(self):
            print('人正在走')
    
    
    class Pig(Animal):
        def run(self):
            print('pig is walking')
    
    
    class Dog(Animal):
        def run(self):
            print('dog is running')
    
    
    peo1 = People()
    pig1 = Pig()
    d1 = Dog()     
    
    # 多态性:一种调用方式,不同的执行效果(多态性)
    def func(obj):
        obj.run()
     	#obj.click()
        #ocj.bite()
        ...
    
    
    func(peo1)
    func(pig1)
    func(d1)
    
    #人正在走
    #pig is walking
    #dog is running
    

    总结:多态性是一个接口(函数func)的多种实现(如obj.run(),obj.talk(),obj.click(),len(obj))

    三、多态性的优点

    1. 增加了程序的灵活性:以不变应万变,不论对象千变万化,使用者都是同一种形式去调用,如func(animal)
    2. 增加了程序额可扩展性:通过继承Animal类创建了一个新的类,使用者无需更改自己的代码,还是用func(animal)去调用
    class Cat(Animal):  # 属于动物的另外一种形态:猫
        def talk(self):
            print('say miao')
    
    
    def func(animal):  # 对于使用者来说,自己的代码根本无需改动
        animal.talk()
    
    
    cat1 = Cat()  # 实例出一只猫
    func(cat1)  # 甚至连调用方式也无需改变,就能调用猫的talk功能
    

    四、鸭子类型

    可以用一个函数去调用任意定义的类中的方法,例如:

    #崇尚鸭子类型:只要走路像鸭子(对象中有某个绑定方法),那你就是鸭子
    
    class Pig:
        def speak(self):
            print('哼哼哼')
    class People:
        def speak(self):
            print('say hello')
    
    pig=Pig()
    pe=People()
    
    def animal_speak(obj):  #同一函数调用
        obj.speak()
    
        
    animal_speak(pig)
    animal_speak(pe)
    

    封装

    一、什么是封装

    封装即将许多东西装进麻袋,然后封口隐藏,使得外部无法访问。

    二、如何隐藏属性/方法

    1. 隐藏属性:通过__变量名来隐藏(可以内部调用)

      • 更安全
      class Person:
          def __init__(self, name):
              self.__name = name
          def check_name(self):
              return '%s' %self.__name   #可以内部调用
      
      p = Person('nick')
      
      #访问name
      print(p.name)
      print(p.__name)
      #以上两种无法获取,已被隐藏。
      print(p.get_name())  #可通过函数内部调用获取
      
      #获取方法
      ①--> print(p.__dict__)  #获取隐藏名
      ②--> print(p._Person__name) 
      
      
    2. 隐藏方法:通过__方法名来隐藏

      • 隔离复杂度
      class Person:
          def __init__(self,name,age):
              self.__name = name
              self.__age = age
          def __speak(self):
              print('6666')
      
      p=Person('nick',89)
      #p.__speak() 无法调用
      
      #获取方法
      ①--> print(Person.__dict__)
      ②--> p._Person__speak()
      
      

      注意:在类内部以__变量名命名的变量,都会被隐藏。在外部放入的__变量名,属性不隐藏。

      举个栗子:

      class Person:
          def __init__(self,name,age):
              self.__name = name
              self.__age = age
          def set_xx(self,xx):
              self.__xx = xx
              print(self.__xx)
      
      p=Person('nick',18)
      
      p.__level = 5 #在类外__变量名放入新变量,不会隐藏属性
      
      p.set_xx('6688')
      

    property装饰器

    一、什么是property

    将方法包装成数据属性

    #计算人的bmi指数
    #property装饰器:把方法包装成数据属性
    
    class Person:
        def __init__(self, name, height, weight):
            self.name = name
            self.height = height
            self.weight = weight
        
        @property
        def bmi(self):
            return self.weight/(self.height**2)
    
    
    p = Person('lqz', 1.82, 70)
    # print(p.bmi()) #用了@property,不需要再加括号调用
    print(p.bmi)
    
    p.name='ppp'
    print(p.name)  #ppp
    
    p.bmi=90
    print(p.bmi) #报错,因为此时的bmi已转为数据属性,是会随着参数而改变的,所以不可修改。
    

    二、property之setter和deleter

    class Person:
        def __init__(self, name, height, weight):
            self.__name = name
            self.__height = height
            self.__weight = weight
        
        @property
        def name(self):
            return '[我的名字是:%s]' %self.__name
        #用property装饰的方法名.setter
        
        @name.setter
        def name(self,new_name):
            # if not isinstance(new_name,str):
            if type(new_name) is not str:
                raise Exception('改不了')
            if new_name.startswith('sb'):
                raise Exception('不能以sb开头')
            self.__name = new_name
    
        # 用property装饰的方法名.deleter
        
        @name.deleter
        def name(self):
            # raise Exception('不能删')
            print('删除成功')
            # del self.__name
    
    p=Person('lqz',1.82,70)
    # print(p.name)
    # p.name='pppp'
    # p.name='xxx'
    #改不了,直接抛一异常
    # p.name=999
    # p.name='sb_nick'
    
    # print(p.name)
    
    del p.name
    print(p.name)
    
  • 相关阅读:
    OPPO R9sPlus MIFlash线刷TWRP Recovery ROOT详细教程
    OPPO R11 R11plus系列 解锁BootLoader ROOT Xposed 你的手机你做主
    努比亚(nubia) M2青春版 NX573J 解锁BootLoader 并进入临时recovery ROOT
    华为 荣耀 等手机解锁BootLoader
    青橙 M4 解锁BootLoader 并刷入recovery ROOT
    程序员修炼之道阅读笔03
    冲刺8
    典型用户模板分析
    学习进度八
    冲刺7
  • 原文地址:https://www.cnblogs.com/fxyadela/p/11426489.html
Copyright © 2011-2022 走看看