组合,封装,访问限制机制,property,多态,抽象类(了解),鸭子类型,多态旋技操作。

组合

1.什么是组合?

组合指的是一个对象中,包含另一个或多个对象。

2.为什么要用组合?

减少代码的冗余。

3.如何使用组合?

耦: 莲藕 ---> 藕断丝连
    - 耦合度越高: 程序的可扩展性越低。
    - 耦合度越低: 程序的可扩展性越高。

总结:

继承:

继承是类与类的关系,子类继承父类的属性/方法,子类与父类是一种 “从属” 关系。

组合:

组合是对象与对象的关系,一个对象拥有另一个对象中的属性/方法,是一种什么有什么的关系。

继承代码演示

# 组合实现:
 选课系统: 老师类,学生类,老师与学生都有名字,年龄,性别
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', 17, 'male')
date_obj = Date(2002, 1, 1)
# date_obj.tell_birth()
# 将date对象赋值到tea1对象的date属性中
tea1.date = date_obj
tea1.date.tell_birth()
# 继承
# 父类
# 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', 17, 'male', 2002, 6, 6)
# stu1 = Student('HCY', 109, 'female', 1910, 11, 11)
#
# print(tea1.name, tea1.age, tea1.sex)
# tea1.tell_birth()
# print(stu1.name, stu1.age, stu1.sex)
# stu1.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', 17, 'male', 2002, 6, 6)
# print(tea1.name, tea1.age, tea1.sex)
# tea1.tell_birth()
# tea1 = Teacher('tank', 17, 'male')
# stu1 = Student('HCY', 109, 'female', 1910, 11, 11)

stu1 = Student('HCY', 109, 'female')
date_obj = Date(1910, 11, 11)
# 学生对象中包含一个自定义日期对象
stu1.date_obj = date_obj
# print(stu1.name, stu1.age, stu1.sex)
# print(stu1.date_obj.year, stu1.date_obj.month, stu1.date_obj.day)
stu1.date_obj.tell_birth()

组合练习

'''
练习需求:
    选课系统:
        1.有学生、老师类,学生与老师有属性 “名字、年龄、性别、课程”,
        2.有方法 老师与学生可以添加课程, 打印学习/教授课程。

    # 组合实现
'''


class People:
    def __init__(self, name, age, sex):
        self.name = name
        self.age = age
        self.sex = sex

    # 打印出生日期方法
    def tell_birth(self):
        print(f'''
        年: {self.date_obj.year}
        月: {self.date_obj.month}
        日: {self.date_obj.day}
        ''')

    # 添加课程
    def add_course(self, course_obj):
        # self.course_name = course_name
        # self.course_price = course_price
        # self.course_time = course_time
        self.course_list.append(course_obj)

    # 打印当前对象中课程列表的所有课程信息
    # ---》 打印所有课程
    def tell_all_course_info(self):
        # 从当前对象中课程列表中取出所有的课程对象
        for course_obj in self.course_list:
            # 通过课程对象.打印课程信息方法
            course_obj.tell_course_info()


class Student(People):
    # 假设从程序开始到灭亡  在实例化时都不修改该对象的属性
    def __init__(self, name, age, sex):
        super().__init__(name, age, sex)
        self.course_list = []


class Teacher(People):
    def __init__(self, name, age, sex):
        super().__init__(name, age, sex)
        self.course_list = []


class Date:
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day


# 定义一个课程类: 课程有: 课程名称, 课程价格, 课程周期
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

    # 定义打印课程方法   : 只打印一个课程信息
    def tell_course_info(self):
        print(f'''
        ====== 课程信息如下 ======
        课程名称: {self.course_name}
        课程价格: {self.course_price}
        课程周期: {self.course_time}
        ''')


# 创建学生对象
stu1 = Student('HCY', 2000, 'female & male')
date_obj = Date('公元19', '11', '11')
stu1.date_obj = date_obj
# stu1.tell_birth()

# 创建课程对象
python_obj = Course('python', 77777, 6)
go_obj = Course('go', 88888, 4)

# 当前学生添加了课程对象
# 添加python课程
stu1.add_course(python_obj)
# 添加go课程
stu1.add_course(go_obj)

# 当前学生打印所有课程信息
stu1.tell_all_course_info()

封装

1.什么是封装?

封装

封装指的是:可以将一堆属性和方法,封装到对象中。

 封: 比如将一个袋子,封起来。
        装: 比如将一堆小猫、小狗和jason装在袋子里。
        # 对象 ---> 相当于一个袋子
封装指的是可以将一堆属性和方法,封装到对象中。

PS: 对象就好比一个 “袋子/容器”,可以存放一对属性和方法。
        PS: 存不是目的,目的是为了取,可以通过 “对象.” 的方式获取属性或方法。

2.为什么要封装?

可以通过 “对象.” 的方式 “存放/获取” 属性或方法。
        对象拥有 "." 的机制。
        方便数据的存取。

3.如何封装?

class User:
            x = 10
            def func():
                pass
        obj = User()
        obj.y = 20
        obj ---> x, func, y

访问限制机制

1.什么是访问限制机制?

凡是在类内部定义的属性或方法,
以__开头的属性或方法名,都会被限制,外部不能 “直接访问” 该属性原型。
PS: 看着像将该属性或方法隐藏起来了。

# python特有的:
        注意: 凡是在类内部定义__开头的属性或方法,都会变形为 _类名__属性/方法。

2.为什么要有访问机制

访问机制:

将一些隐私的数据,隐藏起来,不让外部轻易获取。

好处:

对重要数据获取的逻辑更加严谨, 进而保证了数据的安全.

比如: 将一些隐私的数据,隐藏起来,不让外部轻易获取。

        - 接口:
            可以将一对数据封装成一个接口, 可以让用户调用接口,
            并且通过相应的逻辑,最后再将数据返回给用户。

3.如何实现

接口: 隐私属性可以通过封装一个接口,在接口内做业务逻辑的处理,再把数据返回给调用者.
注意: 在python中,不会强制限制属性的访问,类内部__开头的属性,只是做了一种变形.
若想直接访问, 调用变形后的名字即可.

# demo1
# class User:
#
#     # __开头的属性
#     __name = 'tank'  # __name变形为 ---》 _类名__name
#
#     # __开头的方法
#     def __run(self):
#         print('tank is running...')


# print(User.__name)
# obj = User()
# print(obj._User__name)


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

注意: 在python中,不会强制限制属性的访问,类内部__开头的属性,只是做了一种变形.
若想直接访问, 调用变形后的名字即可.
# demo3:
class ATM:
    # 取钱功能:
    # 1.插入磁卡
    def __insert_card(self):
        print('开始插卡...')
        pass

    # 2.输入密码
    def __input_pwd(self):
        print('输入密码...')
        pass

    # 3.输入取款金额
    def __input_bal(self):
        print('输入取款金额...')
        pass

    # 4.吐钱
    def __output_money(self):
        print('开始吐钱...')
        pass

    # 5.打印流水账单
    def __print_flow(self):
        print('打印流水账单...')
        pass

    # 取款顺序规范接口:
    def withdraw(self):
        # 1.插入磁卡
        self.__insert_card()

        # 2.输入密码
        self.__input_pwd()

        # 3.输入取款金额
        self.__input_bal()

        # 4.吐钱
        self.__output_money()

        # 5.打印流水账单
        self.__print_flow()


amt_obj = ATM()
amt_obj.withdraw()

property

1.什么是property?

是一个python内置的装饰器,可以装饰在"类内部的方法"上。
        可以将该方法调用方式由 ----> 对象.方法() ---> 对象.方法

2.为什么用property?

 PS: 在某些场景下,调用的方法只是用来获取计算后的某个值。
        PS: 必须通过 对象.方法() 方式调用,让该方法看起来像动词。

        让名词的方法,调用时更为合理。
        目的是为了,迷惑调用者,调用的方法误以为是 属性。

3.如何用

@property
# 需求: 计算人体 bmi 指数
# 体重 / 身高的平方
# value = weight / (height * height)
class User:
    def __init__(self, name, weight, height):
        self.__name = name
        self.weight = weight
        self.height = height

    # 获取bmi指数方法
    @property
    def bmi(self):
        # return self.weight / (self.height * self.height)
        return self.weight / (self.height ** 2)


    @property
    def name(self):
        return self.__name

    # 了解: 设置被property装饰后的方法
    # 注意: 需要修改的方法名字要与被property装饰器后的方法一样
  # @name.setter
  # def name(self, value):  # '赵shuai兵' --- 》 value
  #     self.__name = value

  # @name.deleter
  # def name(self):  # 删除属性
  #      del self.__name


user_obj = User('HCY', 100, 1.9)

# user_obj.bmi()()
# print(user_obj.bmi())


# user_obj.bmi()
print(user_obj.bmi)

多态

1.什么是多态?
    多态指的是同一种事物的多种形态.
2.多态的目的:
    多态也称之为多态性, 在程序中继承就是多态的表现形式.
    多态的目的是为了, 让多种不同类型的对象, 在使用相同功能的情况下,调用同一个名字的方法名.
    父类: 定义一套统一的标准.
    子类: 遵循父类统一的标准.
    多态的最终目的: 统一子类编写的规范, 为了让使用者更方便调用相同功能的方法.

3.如何实现:
    - 继承

注意: 在python中,不会强制要求子类必须遵循父类的一套标准,所以出现了抽象类.
class Animal:
    # 吃
    def eat(self):
        pass

    # 喝
    def drink(self):
        pass

    # 叫
    def speak(self):
        pass


# 猪
class Pig(Animal):

    # 吃
    def eat(self):
        print('猪在吃饭')
        pass

    # 喝
    def drink(self):
        pass

    def speak(self):
        print('哼哼哼~~~')


# 猫
class Cat:
    # 吃
    def eat(self):
        print('猫在吃饭')
        pass

    # 喝
    def drink(self):
        pass

    def speak(self):
        print('喵喵喵~~')


# 狗
class Dog:
    # 吃
    def eat(self):
        print('狗在吃饭')
        pass

    # 喝
    def drink(self):
        pass

    def speak(self):
        print('汪汪汪~~~')


# 正确教材
pig = Pig()
cat = Cat()
dog = Dog()

pig.speak()
cat.speak()
dog.speak()

抽象类(了解):

1.是什么?
    abc模块  abstract_class
2.使用的目的?
    强制子类必须遵循父类的一套标准.

3.如何使用
    import 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):
        print('猪在吃饭')
        pass

    # 喝
    def drink(self):
        pass

    def speak(self):
        print('哼哼哼~~~')

    # 派生
    def run(self):
        pass

pig = Pig()

鸭子类型:

1.什么是鸭子类型?
    在不知道当前对象是何物的情况下,但是你长得像鸭子,那么你就是鸭子类型.
在python中,不推荐使用抽象类强制限制子类的定义,但是推荐类都遵循鸭子类型.

- 继承:
    耦合性太高,程序的可扩展性差

- 鸭子类型:
    耦合度低,程序的可扩展性强
    
列:
# 猪
class Pig:
    # 吃
    def eat(self):
        print('猪在吃饭')
        pass
    # 喝
    def drink(self):
        pass
    def speak(self):
        print('哼哼哼~~~')


# 猫
class Cat:
    # 吃
    def eat(self):
        print('猫在吃饭')
        pass
    # 喝
    def drink(self):
        pass
    def speak(self):
        print('喵喵喵~~')

# 狗
class Dog:
    # 吃
    def eat(self):
        print('狗在吃饭')
        pass
    # 喝
    def drink(self):
        pass
    def speak(self):
        print('汪汪汪~~~')

多态旋技操作

代码演示

# # 猫
# class Cat:
#     # 吃
#     def eat(self):
#         print('猫在吃饭')
#         pass
#     # 喝
#     def drink(self):
#         pass
#     def speak(self):
#         print('喵喵喵~~')
#
# # 狗
# class Dog:
#     # 吃
#     def eat(self):
#         print('狗在吃饭')
#         pass
#     # 喝
#     def drink(self):
#         pass
#     def speak(self):
#         print('汪汪汪~~~')
#
# dog = Dog()
# cat = Cat()
# pig = Pig()
#
# def BARK(animal):
#     animal.speak()

# BARK(dog)
# BARK(cat)
# BARK(pig)

汪汪汪~~~
喵喵喵~~
哼哼哼~~~
原文地址:https://www.cnblogs.com/WQ577098649/p/11656019.html