• 组合&多态&封装


    组合&多态&封装


    一、组合


    1.1什么是组合

    对象的属性是另一个对象

    class Foo:
        pass
    class Bar:
        pass
    
    f = Foo()
    f.bar = Bar()

    1.2 为什么要用组合

    • 减少代码冗余

    1.3 如何使用组合

    首先我们有老师类和学生类,他们都有共同的属性,课程姓名,课程价格,课程时间,为了避免代码冗余,我们就需要用组合。

    #这样的代码,我们看起来是不是和繁琐,那我们就把他们相同的属性拿出来,重新定义一个类,用的时候,我们就直接传入这个对象就好了。
    class Person:   #定义一个基类
        school = 'oldboy'
    
    class Teacher(Person):
        def __init__(self,name,age,level,course_name,course_price,course_time):
            self.name = name
            self.age = age
            self.level = level
            self.course_name = course_name
            self.course_price = course_price
            self.course_time = course_time
    
    class Student(Person):
        def __init__(self, name, age, level, course_name, course_price, course_time):
            self.name = name
            self.age = age
            self.level = level
            self.course_name = course_name
            self.course_price = course_price
            self.course_time = course_time
    #这样写的话代码会更清晰
    class Person:
        school = 'oldboy'
    
    class Teacher(Person):
        def __init__(self,name,age,level,course):
            self.name = name
            self.age = age
            self.level = level
            self.course = course  #course是课程对象,表示老师教授的课程
    
    class Student(Person):
        def __init__(self, name, age,course):
            self.name = name
            self.age = age
            self.course = course  #course是课程对象,表示老师教授的课程
    
    class Course:  #定义一个课程类
        def __init__(self,course_name, course_price, course_time):
            self.course_name = course_name
            self.course_price = course_price
            self.course_time = course_time
    
    #产生对象
    course = Course('python','20000',7)
    stu1 = Student('jiayi',18,course)
    teacher1 = Teacher('tank',20,'good',course)
    #查看老师教授的课程名
    print(teacher1.course.course_name)
    #查看学生选择的课程名
    print(stu1.course.course_name)
    
    #进阶版
    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):
            self.name = name
            self.age = age
            #course是课程对象,表示老师教授的课程
            self.course_list = []   #定义一个课程列表的空列表
        def choose_course(self, course):  # 定义一个选择课程的方法
            # 把课程对象追加到学生选课的列表中
            self.course_list.append(course)
    
        def tell_all_course(self):  # 定义一个选择课程的方法
            # 循环学生选课列表,每次拿出一个课程对象
            for course in self.course_list:
                # 课程对象.name  取到课程名字
                print(course.course_name)
    
    
    class Course:  #定义一个课程类
        def __init__(self,course_name, course_price, course_time):
            self.course_name = course_name
            self.course_price = course_price
            self.course_time = course_time
    
    #产生对象
    course = Course('python','20000',7) #把课程的参数传进去
    stu1 = Student('jiayi',18)
    stu1.choose_course(course)   #输出学生1的课程选择
    
    stu2 = Student('ypp',18)
    stu2.choose_course(course)
    stu2.choose_course(Course('Linux',20000,7))
    # 查看stu2选的所有课程名称
    #方式一(通过对象的绑定方法)
    stu2.tell_all_course()
    #方式二(通过普通函数)
    def tell_all_course(student):
        for course in student.course_list:  #循环课程里面的对象
            print(course.course_name)  #输出课程姓名
    tell_all_course(stu2)

    1.4 继承和组合都在什么时候用

    什么什么的时候用继承。eg:老师、学生是人

    什么什么的时候用哪个组合。eg:老师、学生有课程

    二、多态与多态性


    2.1 什么是多态

    ​ 一类事物的多种形态(同一类事物的不同形态)eg:水有冰,水蒸气。动物有 猪、狗、人

    class Animal:  #定义一个动物类
        def speak(self):  #定义一个speak的方法
            pass
    
    class Pig(Animal):
        def speak(self):  #pig会speak
            print('哼哼哼')
    
    class Dog(Animal):
        def speak(self):  #Dog会speak
            print('汪汪')
    
    class People(Animal):
        def speak(self):  #people会speak
            print('say hello')
    
    """产生对象"""
    pig=Pig()
    dog=Dog()
    people=People()
    """调用方法"""
    pig.speak()
    dog.speak()
    people.speak()
        

    2.2 如何用多态

    • 方法一:用abc实现接口统一化,约束代码(用的比较少)
    import abc
    #第一在括号中写metaclass=abc.ABCMeta
    class Animal(metaclass=abc.ABCMeta):
        #第二在要约束的方法上,写abc.abstractmethod装饰器
        @abc.abstractmethod
        def speak(self):
            pass
    class Pig(Animal):
        def speak(self):   #此时必须用speak,其他变量名都不行,因为做了约束
            print('哼哼哼')
    class Dog(Animal):
        def speak(self):  #此时必须用speak,其他变量名都不行,因为做了
            print('汪汪')
    
    class People(Animal):
        def speak(self):   #此时必须用speak,其他变量名都不行,因为做了
            print('say hello')
    
    #产生对象
    pig = Pig()  #方式一
    pig.speak()   #这样我们就可以获取'哼哼哼'
    
    #定义了一个函数,但是没有利用到多态性
    def animal_speak(obj):  #定义函数   #方式二
        obj.speak()
    pig = Pig()  #产生对象
    animal_speak(pig)
    -------------------------------------------------
    哼哼哼
    • 方法二:用异常处理来实现(常用)
    class Animal():
        def speak(self):
            #主动抛出异常
            raise Exception('你得给我重写它啊,我已经做了代码约束')
    class Pig(Animal):
        #此时必须用speak,其他变量名都不行,因为做了约束
        #代码运行时抛出了异常,所以必须把不一样的变量名改过来
        def speak(self):   
            print('哼哼哼')
    class People(Animal):
        def speak(self):
            print('say hello')
            
            
    pig=Pig()
    pe=People()
    def animal_speak(obj):
        obj.speak()
    
    animal_speak(pig)
    animal_speak(pe)
    • 方法三:崇尚鸭子类型。只要走路像鸭子(对象中有某个绑定方法),那你就是鸭子
    class Pig:
        def speak(self):  #只要是speak变量名,就把他看成多态
            print('哼哼哼')
    class People:
        def speak(self):  #只要是speak变量名,就把他看成多态
            print('say hello')
    
    pig=Pig()
    pe=People()
    def animal_speak(obj):
        obj.speak()
        
    animal_speak(pig)
    animal_speak(pe)

    2.3 什么是多态性

    ​ 一类事物都有相同的特性,但特性都不一样

    ​ eg:动物都会speak,但是人speak是’say hello‘,但是猪speak是’哼哼哼‘。

    2.4 多态性的好处

    • 增加程序的灵活性
    • 增加了程序的可扩展性(假如再来一个长颈鹿,它也会speak,我们就会还用self.speak = speak

    三、封装


    3.1 什么是封装

    ​ 隐藏对象的属性和方法,仅对外提供公共访问方式,也就是说我们那一个麻袋,把小猫,小狗,小王八都装到这个麻袋里面。

    3.2 如何用封装

    • 把东西包装进去,隐藏起来访问不到

    3.3 如何用代码实现封装

    隐藏属性:通过__变量名来隐藏属性,隐藏之后外部访问不到,只有内部能够访问

    #封装name属性
    class Person:
        def __init__(self,name,age):
            self.__name = name  #封装name属性
            self.age = age
        def get_name(self):
            return self.__name  #只能拿不能改
    #产生对象
    p = Person('jiayi',20)
    # 查看属性
    print(p.age)  #20
    # print(p.__name)  #报错,获取不到
    print(p.get_name())   #可以获取到
    
    
    # 获取name属性(隐藏的属性访问不到?实际上有方法能访问到)
    print(p._Person__name)   #通过'_父类__属性'获取
    print(p.__dict__)   #获取对象的所有属性,会打印出来

    目的:为了提高安全性,防止被修改

    隐藏方法:通过__方法名来隐藏方法,隐藏之后外部访问不到,只有内部能够访问

    class Person:
        def __init__(self,name,age):
            self.name=name
            self.age=age
        def __speak(self):  #隐藏speak方法
            print('6666')
    
    p=Person('nick',89)  #产生对象,并传值
    p.__speak()   #获取speak方法,报错
    print(Person.__dict__)   #获取Person的所有属性
    
    # 获取speak方法(隐藏的属性访问不到?实际上有方法能访问到)
    p._Person__speak()   #获取speak方法

    目的:隔离复杂度 eg:傻瓜相机

    3.4 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)
            # return self.weight/(self.height*self.height)
    p=Person('yjy',1.73,57)
    # print(p.bmi())
    print(p.bmi)

    3.5 封装与扩展性

    # 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('yjy',1.73,57)
    # print(p.name)
    # p.name='pppp'
    # p.name='xxx'
    #改不了,直接抛一异常
    # p.name=999   #测试@name.setter
    # p.name='sb_nick'  #测试@name.deleter
    
    # print(p.name)
    
    del p.name
    print(p.name)     #会输出删除成功,但是并没有删除成功,是删除不了的 
  • 相关阅读:
    OleDbCommand 的用法
    递归求阶乘
    C#重写窗体的方法
    HDU 5229 ZCC loves strings 博弈
    HDU 5228 ZCC loves straight flush 暴力
    POJ 1330 Nearest Common Ancestors LCA
    HDU 5234 Happy birthday 01背包
    HDU 5233 Gunner II 离散化
    fast-IO
    HDU 5265 pog loves szh II 二分
  • 原文地址:https://www.cnblogs.com/lulingjie/p/11528944.html
Copyright © 2020-2023  润新知