• 【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)
    
  • 相关阅读:
    M1阶段的开发过程的一些反思
    Alpha版本发布说明
    Alpha版本BUG BASH
    Notes of Daily Scrum Meeting(11.19)
    Notes of Daily Scrum Meeting(11.17)
    Notes of Daily Scrum Meeting(11.15)
    Notes of Daily Scrum Meeting(11.14)
    flask_sqlalchemy介绍
    SQLAlchemy 简单笔记
    Python-3.6 安装pycrypto 2.6
  • 原文地址:https://www.cnblogs.com/fxyadela/p/11426489.html
Copyright © 2020-2023  润新知