组合,封装,多态

目录

  • 组合
    • 什么是组合
    • 为什么要使用组合
    • 如何使用组合
    • 组合练习
  • 封装
    • 什么是封装
    • 为什么要封装
    • 如何封装
  • 访问限制机制
    • 什么是访问限制机制
    • 访问限制机制的目的
  • property
    • 什么是property
    • 为什么要用property
    • 如何使用property
  • 多态
    • 什么是多态
    • 多态的目的
    • 如何实现:
  • 抽象类
  • 鸭子类型
  • 多态炫技操作

组合

什么是组合

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

为什么要使用组合

减少代码冗余

如何使用组合

继承实现:

# 选课系统:老师类,学生类,老师与学生都有名字、年龄、性别

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)

你可能感兴趣的