zoukankan      html  css  js  c++  java
  • 组合,封装,多态

    组合

    什么是组合

    组合指的是一个对象中的属性,是另一个对象

    为什么要使用组合

    减少代码冗余

    如何使用组合

    继承实现:

    # 选课系统:老师类,学生类,老师与学生都有名字、年龄、性别
    
    class People:
        def __init__(self, name, age, sex, year, month, day):
            self.name = name
            self.age = age
            self.sex = sex
            self.year = year
            self.month = month
            self.day = day
    
        def tell_birth(self):
            print(f'''
            === 出生年月日 ===
            年: {self.year}
            月: {self.month}
            日: {self.day}
            ''')
    
    
    class Teacher(People):
        def __init__(self, name, age, sex, year, month, day):
            super().__init__(name, age, sex, year, month, day)
    
    
    class Student(People):
        def __init__(self, name, age, sex, year, month, day):
            super().__init__(name, age, sex, year, month, day)
    
    
    tea1 = Teacher('tank', 18, 'male', 2001, 1, 1)
    tea1.tell_birth()
    
    

    组合实现:

    class People:
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
    
    
    class Teacher(People):
        def __init__(self, name, age, sex):
            super().__init__(name, age, sex)
    
    class Student(People):
        def __init__(self, name, age, sex):
            super().__init__(name, age, sex)
    
    
    class Date:
        def __init__(self, year, month, day):
            self.year = year
            self.month = month
            self.day = day
    
        def tell_birth(self):
            print(f'''
            === 出生年月日 ===
            年: {self.year}
            月: {self.month}
            日: {self.day}
            ''')
    
    
    tea1 = Teacher('tank', 18, 'male')
    date_obj = Date(2001, 1, 1)
    # 将date对象赋值给tea1对象的属性date中
    tea1.date = date_obj
    tea1.date.tell_birth()
    

    总结:

    • 继承是类与类的关系,一种什么是什么的关系,子类与父类是一种从属关系
    • 组合是对象与对象的关系,一种什么有什么的关系,一个对象拥有另一个对象

    组合练习

    '''
    选课系统需求:
        1.学生类,老师类, 学生和老师都有课程属性, 每一门课程都是一个对象.
            课程: 课程名字,课程周期,课程价钱
    
        2.学生和老师都有选择课程的功能, 还有打印所有课程的功能.
    '''
    
    
    class People:
        def __init__(self, name, age, sex):
            self.name = name
            self.age = age
            self.sex = sex
    
        def add_course(self, course_obj):
            self.course_list.append(course_obj)
    
        def tell_all_course(self):
            # 拿到当前对象的课程列表,列表中存放的是一个个对象
            for course_obj in self.course_list:
                # 每一个课程对象查看课程信息的方法
                course_obj.tell_course_info()
    
    
    class Teacher(People):
        def __init__(self, name, age, sex):
            super().__init__(name, age, sex)
            self.course_list = []
    
    
    class Student(People):
        def __init__(self, name, age, sex):
            super().__init__(name, age, sex)
            self.course_list = []
    
    
    class Course:
        def __init__(self, course_name, course_period, course_price):
            self.course_name = course_name
            self.course_period = course_period
            self.course_price = course_price
    
        def tell_course_info(self):
            print(f'''
            课程名称:{self.course_name}
            课程周期:{self.course_period}
            课程价格:{self.course_price}
            ''')
    
    tea1 = Teacher('tank', 18, 'male')
    stu1 = Student('小明', 18, 'male')
    
    python_obj = Course('python', 6, 2)
    linux_obj = Course('linux', 6, 1)
    
    tea1.add_course(python_obj)
    tea1.add_course(linux_obj)
    
    tea1.tell_all_course()
    

    封装

    什么是封装

    封装指的是把一堆属性封装到一个对象中

    存数据的目的是为了取,对象可以"."的方式,获取属性

    为什么要封装

    封装的目的是为了方便存取,可以通过对象.属性的方式获取属性

    如何封装

    特征:变量 ---> 数据属性

    技能:函数 ---> 方法属性

    在类内部,定义一堆属性(特征与技能)

    访问限制机制

    什么是访问限制机制

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

    访问限制机制的目的

    一堆隐私的属性与不能被外部轻易访问的属性,可以隐藏起来,不能被外部直接调用

    好处:对重要数据获取的逻辑更加严谨,进而保护了数据的安全

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

    class Foo:
        # 数据属性
        __name = 'tank'
    
        # 方法属性
        def __run(self):
            print('running...')
    
        def get_name(self):
            return self.__name
    
        def set_name(self):
            self.__name = 'cwz'
    
    foo = Foo()
    # print(foo.__name)
    foo.set_name()
    print(foo.get_name())
    
    print(foo._Foo__name)  # _类名__属性名
    

    注意:在python中,不会强制限制属性的访问,类内部__开头的属性,只是做了一种变形。若想直接访问,调用变形后的名字即可

    class Teacher:
        def __init__(self, name, age, sex):
            self.__name = name
            self.__age = age
            self.__sex = sex
    
        # 接口:打印用户信息接口
        def get_info(self):
            user = input('user:').strip()
            pwd = input('pwd:').strip()
            if user == 'tank' and pwd == '123':
    
                print(f'''
                    姓名:{self.__name}
                    年龄:{self.__age}
                    性别:{self.__sex}
                    ''')
    
        # 接口:修改用户信息接口
        def set_info(self, name, age, sex):
            if not isinstance(name, str):
                raise TypeError('名字必须要使用字符串')
    
            if not isinstance(age, int):
                raise TypeError('年龄必须要使用数字')
    
            if not isinstance(sex, str):
                raise TypeError('性别必须要使用字符串')
    
            self.__name = name
            self.__age = age
            self.__sex = sex
    
    t1 = Teacher('tank', 18, 'male')
    t1.get_info()
    
    class ATM:
        # 插卡
        def __insert_card(self):
            print('开始插卡')
    
        # 输入密码
        def __input_pwd(self):
            print('开始输入密码')
    
        # 输入取款金额
        def __input_money(self):
            print('输入取款金额')
    
        # 开始吐钱
        def __get_money(self):
            print('开始吐钱')
    
        # 打印账单
        def __print_flow(self):
            print('打印账单')
    
        # 取钱接口
        def withdraw(self):
            self.__insert_card()
            self.__input_pwd()
            self.__input_money()
            self.__get_money()
            self.__print_flow()
            print('程序执行完毕')
    
    atm = ATM()
    atm.withdraw()
    

    property

    什么是property

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

    为什么要用property

    使用它的目的,是将类内部的方法(def 方法名() 变成了(def 方法))

    在对象使用某个方法时,将对象.方法()变成了对象.方法

    如何使用property

    
    '''
    计算人的bmi:bmi值 = 体重 / (身高 * 身高)
    '''
    
    class People:
        def __init__(self, name, weight, height):
            self.name = name
            self.weight = weight
            self.height = height
    
        @property
        def bmi(self):
            return self.weight / (self.height ** 2)
    
    p = People('cwz', 180, 1.8)
    print(p.bmi)
    

    注意:不能对被装饰过的方法属性修改

    但是也可以修改(了解)

    class People:
        def __init__(self, name, weight, height):
            self.name = name
            self.weight = weight
            self.height = height
    
        @property
        def bmi(self):
            return self.weight / (self.height ** 2)
    
        @property
        def get_name(self):
            return self.name
    
        # 修改
        @get_name.setter
        def set_name(self, val):
            self.name = val
    
        # 删除
        @get_name.deleter
        def del_name(self):
            del self.name
    
    
    p = People('cwz', 180, 1.8)
    # print(p.bmi)
    
    p.set_name = 'nick'
    # print(p.get_name)
    
    del p.del_name
    
    # print(p.get_name)
    

    多态

    什么是多态

    多态指的是同一种事物的多种形态

    多态的目的

    多态也称之为多态性,在程序中继承就是多态的表现形式

    多态的目的是为了,让多种不同类型的对象,在使用相同功能的情况下,调用同一个名字的方法名

    父类:定义一套统一的标准

    子类:遵循父类统一的标准

    多态的最终目的:统一子类编写的规范,为了让使用者更方便调用相同方法的功能

    如何实现:

    继承

    抽象类

    在python中,不会强制要求子类必须遵循父类的一套标准,所以出现了抽象类

    abc模块

    会强制子类遵循父类的一套标准

    import abc
    
    
    class Animal(metaclass=abc.ABCMeta):
        @abc.abstractmethod
        def eat(self):
            pass
    
        @abc.abstractmethod
        def drink(self):
            pass
    
        @abc.abstractmethod
        def speak(self):
            pass
    
    
    class Pig(Animal):
        def eat(self):
            pass
    
        def drink(self):
            pass
    
        def jiao(self):    # 强制使用与父类相同的标准,这样会报错
            print('哼哼哼。。。')
    
    
    pig = Pig()
    pig.jiao()
    

    鸭子类型

    在不知道当前对象是什么的情况下,但你长得像鸭子,那么你就是鸭子类型

    在python中,不推荐使用抽象类强制子类的定义,但是推荐子类都遵循鸭子类型

    • 继承:耦合性太高,程序的可扩展性差
    • 鸭子类型:耦合度第,程序的可扩展性强

    多态炫技操作

    class Animal:
        def eat(self):
            pass
    
        def drink(self):
            pass
    
        def speak(self):
            pass
    
    
    class Pig(Animal):
        def eat(self):
            pass
    
        def drink(self):
            pass
    
        def speak(self):
            print('哼哼哼。。。')
    
    
    class Cat(Animal):
        def eat(self):
            pass
    
        def drink(self):
            pass
    
        def speak(self):
            print('喵喵喵。。。')
    
    
    class Dog(Animal):
        def eat(self):
            pass
    
        def drink(self):
            pass
    
        def speak(self):
            print('汪汪汪。。。')
    
    
    pig = Pig()
    dog = Dog()
    cat = Cat()
    
    
    def BARK(animal):
        animal.speak()
    
    
    BARK(dog)
    BARK(pig)
    BARK(cat)
    
  • 相关阅读:
    win10下以管理员身份打开hosts文件
    使用Dockerfile构建镜像命令自己的理解
    我们在删除镜像的时候被告知有容器正在使用,可是容器已经被停止了
    Docker构建镜像过于缓慢解决-----Docker构建服务之部署和备份jekyll网站
    VMware虚拟机ubuntu显示屏幕太小解决办法
    树莓派3B从装系统到安装RYU过程
    树莓派3b 换国内源 更新源
    Raspbain系统无屏幕无网线通过ssh远程连接树莓派设置wifi步骤
    Mplayer 隐藏边框和显示位置的方法
    使用mplayer查看摄像头
  • 原文地址:https://www.cnblogs.com/setcreed/p/11656979.html
Copyright © 2011-2022 走看看