Python_面向对象的三大特征_封装_继承_多态(11)

目录:

一、封装 二、继承 三、多态 四、综合案例

创作不易,各位看官,点个赞收藏、关注必回关、QAQ、您的点赞是我更新的最大动力!


一、封装

(一)什么是封装

封装,是面向对象的第一个特性,体现了对数据的有效组织和数据安全性的保护机制, 在传统的编码中,面向对象编程思想中的类型体现的是对数据的描述,而对象体现的则是个 体数据的展示,既然是个体数据反映的就是生活中的私有数据,就需要考虑其访问安全性, 反应到生活中就是每个个体私有数据的保护,如图所示:在这里插入图片描述
(二)封装的基本语法

1、所有属性私有化

python 语言在实现封装时,一些项目规范中约定使用一个下划线开头的属性为当前对象私 有属性,不允许外界访问,但是一个下划线开头的属性是可以被直接访问的。
语法上两个下划线开头的属性或者方法,在外界是不允许直接访问的。
语法上两个下划线开头并且结尾的属性有特殊的应用场合。
class Manager:
    """管理员类型"""

    def __init__(self, username, password, nickname, email, phone):
        """初始化属性数据:所有属性私有化"""
        self.__username = username  # 标准的私有化语法
        self.__password = password  # 标准的私有化语法
        self.__nickname = nickname  # 标准的私有化语法

2、访问私有属性
属性私有化之后,给每个属性提供访问属性的 get 方法和设置赋值的 set 方法,通过固 定语法的格式提供给对象外部的调用者

  • 一般访问 str
#属性私有化之前,用户信息可以直接访问并修改
class User:
    """用户类型"""
    def __init__(self,name,age):
        """用户姓名和年龄"""
        self.name = name
        self.age = age
    def __str__(self):
        """打印用户信息"""
        return f"我叫{self.name},今年{self.age}岁"

user = User("小明",23)
print(user)
  • 使用setter和getter访问
    def set__username(self, username):
        """给私有属性设置数据的方法"""
        self.__username = username

    def get__username(self):
        """获取私有属性数据的方法"""
        return self.__username
  • 使用限定条件访问

作用:就是在开发过程中保护核心代码,在类的外部不能使用(对象不能调用私有方法)
3、私有方法

class A:
    def __test1(self):
        print("--in test1--")

    def test2(self):
        self.__test1()
        print("--in test2--")
a = A()
# a.__test1() #对象不能调用私有方法
a.test2()

4、私有属性修改

class User:
    """用户类型"""
    def __init__(self,name,age):
        """用户姓名和年龄"""
        # self.name = name
        # self.age = age
        self.__name = name
        self.__age = age

    def __str__(self):
        """打印用户信息"""
        # return f"我叫{self.name},今年{self.age}岁"
        return f"我叫{self.__name},今年{self.__age}岁"
user = User("小明",23)
# print(user)
#属性私有化之前,对象的属性如下
# print(user.__dict__) #{'name': '小明', 'age': 23}
# user.name = "稳稳" #可以修改


#属性私有化之后,对象的属性如下
print(user.__dict__) #{'_User__name': '小明', '_User__age': 23}
# user.__name = "稳稳" #只是增加属性
# print(user.__dict__)

user._User__name = "稳稳"
print(user)

返回文章目录

二、继承

(一)什么是继承
让类与类之间产生父子关系,子类可以拥有父类的属性和方法(私有属性和私有方法无法继承)
父类用于被继承的类,称为父类,也叫基类,或者超类
子类继承其它类的类,称为子类,也叫派生类
查看继承父类的_ base_()

继承的作用: 可以提高代码的复用率

(二)继承的基本语法

"""
继承的基本语法
    父类:被继承的类型,需要重复利用的代码包含在父类中
    子类:当前类型,继承其他类型,重复使用其他类型中的代码

    python中的所有类型都是直接或者间接继承自object
    都是从object派生出来的!
    子类继承父类,父类派生子类!
"""


class Father:
    """父亲类型"""

    def __init__(self, name, gender, age):
        self.name = name
        self.gender = gender
        self.age = age

    def sleep(self):
        print("睡觉时间到了,准备午休..")

    def study(self):
        print("充电时间到了,准备学习..")


class Son(Father):
    """儿子类型:继承父亲类型"""
    pass


tom = Son("汤姆", "男", 18)
print(tom.name, tom.age, tom.gender)
tom.study()
tom.sleep()

复用性体现 [使用父类的属性]:

"""
继承中父类的代码的复用
"""
class Animal:
    """动物类型"""

    def __init__(self, nickname, amtype):
        self.nickname = nickname
        self.amtype = amtype

    def move(self):
        print("某个动物在运动中...")


class Beast(Animal):
    """地上跑的"""
    pass


class Bird(Animal):
    """天上飞的"""
    pass


class Fish(Animal):
    """水里游的"""
    pass


cat = Beast("汤姆猫", "走兽")
beita = Bird("开飞机的贝塔", "飞禽")
xiaolu = Fish("水里的美人鱼", "游鱼")

cat.move()
beita.move()
xiaolu.move()

复用性高级[使用父类的属性,自己定义自己的属性]:

"""
继承中父类的代码的复用升级
从一个问题说起:
    直接使用父类不好吗?为什么要写那么多子类的空代码?
    灵机一动:难道为了一行代码一块钱?

① 通过子类继承父类
    子类能更好的更精确的描述生活中的某个对象
    猫 = 动物()
    猫 = 走兽()  更加准确
② 通过子类继承父类
    子类在复用父类代码的情况下,能扩展自己的属性
    父类的每个子类,都有互相不同的地方~
    所以才将多个子类相同的代码声明在父类中复用
    子类中互不相同的代码保留在自己子类中使用
"""
class Animal:
    """动物类型"""

    def __init__(self, nickname, amtype):
        self.nickname = nickname
        self.amtype = amtype

    def move(self):
        print("某个动物在运动中...")


class Beast(Animal):
    """地上跑的"""

    def __init__(self, nickname, amtype, blood):
        # 子类如果一旦编写__init__()方法
        # 就必须显式的调用父类的__init__()方法初始化父类数据
        # Animal.__init__(nickname, amtype)
        # super(Beast, self).__init__(nickname, amtype)
        # ① 复用父类的代码
        super().__init__(nickname, amtype)
        # ② 子类自己的代码
        self.blood = blood


class Bird(Animal):
    """天上飞的"""

    def __init__(self, nickname, amtype, attact):
        # ① 复用父类的代码
        super().__init__(nickname, amtype)
        # ② 子类独有的代码
        self.attact = attact

class Fish(Animal):
    """水里游的"""
    pass


cat = Beast("汤姆猫", "走兽", 2000)
beita = Bird("开飞机的贝塔", "飞禽", 100)
xiaolu = Fish("水里的美人鱼", "游鱼")

print(cat.nickname, cat.amtype, cat.blood)
print(beita.nickname, beita.amtype, beita.attact)
cat.move()
beita.move()
xiaolu.move()

(三)方法覆盖 [重写]

简单的来说,就是将父类里面的方法,在子类里面重写

"""
方法重载:
    子类中声明和定义了父类中相同名称和参数的方法
"""
class Animal:
    """动物类型"""
    def __init__(self, nickname):
        self.nickname = nickname

    def move(self):
        print(f"{self.nickname}在移动中..")


class Beast(Animal):
    """走兽"""

    def move(self):
        print(f"{self.nickname}在快速的奔跑中..")


class Bird(Animal):
    """飞禽"""
    def move(self):
        print(f"{self.nickname}在愉快的飞行中..")


class Fish:
    """游鱼"""
    def __init__(self, nickname):
        self.nickname = nickname

    def swimming(self):
        """移动的方法"""
        print("飞快的游走中...")


cat = Beast("汤姆猫")
shuke = Bird("舒克的飞机")
# 调用的是同一个方法,但是执行的是不同的结果
cat.move()  # 汤姆猫在快速的奔跑中..
shuke.move()  # 舒克的飞机在愉快的飞行中..

xiaolu = Fish("小鹿")
xiaolu.swimming()
'''
通过方法重写
① 理解继承的代码的重用型
② 继承关系中,对于子类中的代码有了一定的约束性
③ 方法覆盖,体现了一种运行时状态改变-体现了多态
    如果子类没有重写父类的方法,就直接执行父类的方法
    如果子类重写了父类的方法,就执行子类重写后的方法
'''

(四)子类访问父类 [使用父类中的super()方法,三种方法]

坦克大战:

"""
方法重载案例:坦克大战中的坦克
"""
class Tank:
    """坦克类型"""

    def fire(self):
        print("坦克开火了,发射子弹(10行代码)...")


class HeroTank(Tank):
    """英雄坦克:玩家控制"""

    def fire(self):
        # 子类中额外添加的功能
        print("英雄坦克,模拟玩家按下空格键,发射子弹[事件(按下空格动作)操作]")
        # 复用父类中发射子弹的代码
       	# Tank.fire(self) 		  #1.父类名.方法名(self)
       	# super(Tank,self).fire() #2.super(当前类名,self).方法名()
        super().fire()		      #3.super().fire()


class EnemyTank(Tank):
    """敌方坦克:电脑控制"""

    def fire(self):
        print("添加代码,控制坦克间隔随机时间发射子弹")
        super().fire()


hero = HeroTank()
hero.fire()

enemy = EnemyTank()
enemy.fire()

综合案例-宠物医院:

"""
宠物医院案例
    面向对象开发
"""
import time


class Pet:
    """宠物父类"""

    def __init__(self, nickname, health):
        self.nickname = nickname  # 昵称
        self.health = health  # 健康状态[0~30病危|30-60生病|60-80亚健康|80-100健康]

    def recovery(self):
        """康复的行为"""
        while self.health <= 65:
            self.health += 5
            time.sleep(0.5)
            print(f"{self.health}>>正在恢复中.....")


class Hospital:
    """宠物医院"""

    def __init__(self, name):
        self.name = name

    def care(self, pet):
        """治疗的行为"""
        # 判断某个对象是否属于某种类型:判断pet对象是否Pet类型
        if isinstance(pet, Pet):
            # 医院开始治疗,用药
            print(f"开始治疗{pet.nickname}")
            # 宠物开始恢复
            pet.recovery()
        else:
            print("宠物医院只接受宠物进行治疗....")


class Cat(Pet):
    """宠物猫"""
    pass


class Dog(Pet):
    """宠物狗"""
    pass


class Person:

    def __init__(self, nickname, health):
        self.nickname = nickname
        self.health = health

    def recovery(self):
        while self.health <= 60:
            self.health += 20
            print("正在快速的恢复中...")

hospital = Hospital("玛利亚宠物医院")
# cat = Cat("汤姆猫", 30)
# hospital.care(cat)
# print("最终宠物的健康值:", cat.health)

dog = Dog("二哈", 20)
hospital.care(dog)
print("最终二哈的健康值:", dog.health)

# damu = Person("大牧", 50)
# hospital.care(damu)


(五)多继承 [隔代继承]

1、基本语法
python 语法中提供了多继承的语法,用于体现生活中一个对象多种角色的情况,具体 语法上是将多个继承的类型依次写在子类声明后面的括号中

隔代继承:

class Animal:

    def __init__(self):
        print("我是动物")


class dog(Animal):

    pass

class cat(dog):
    pass

#创建对象
cat_tom = cat() #输出  “我是动物”

多继承:

"""
多继承关系
    多继承需要注意的问题:如果多个父类中出现了相同名称的属性、方法怎么办?
"""
class Son:
    """儿子类型"""

    def respect(self):
        """尊敬,孝顺"""
        print("百善孝为先")

    def play(self):
        print("作为儿子角色,越快的玩耍中...")


class Husband:
    """丈夫类型"""

    def love(self):
        """恩爱的行为"""
        print("相濡以沫")

    def play(self):
        print("作为丈夫的角色,王者荣耀中...")


class Father:
    """老爹类型"""

    def care(self):
        """爱护的行为"""
        print("家里的千金,万般呵护..")


class Teacher:
    """老师类型"""

    def teach(self):
        """授课的行为"""
        print("前人栽树....")


class Person(Son, Husband, Father, Teacher):
    """人的类型"""
    pass

    # def play(self):
    #     print("Person 愉快的玩耍中...")


wenwen = Person()
wenwen.play()  # Son, Husband


# # 儿子
# if isinstance(wenwen, Son):
#     wenwen.respect()
#
# # 丈夫
# if isinstance(wenwen, Husband):
#     wenwen.love()
#
# # 父亲
# if isinstance(wenwen, Father):
#     wenwen.care()
#
# # 老师
# if isinstance(damu, Teacher):
#     wenwen.teach()

2、注意事项
多继承关系中,一个类型继承多个类型,如果在继承的多个类型中出现了相同名称的属 性或者方法(当然如果出现一般都是软件结构设计上存在问题),就会出现子类如果使用到了 这样的属性和方法,优先调用的是继承的那个类型的属性或者方法了 上述问题如果一旦出现,有两种解决方案:

  • 重新设计软件架构,对类型中的属性进行规范整理
  • 梳理调用顺序,按照语法语义上的顺序执行

在这里插入图片描述
运行程序只看输出“动物的爱”
第一种方案如果一旦实施就是常规编程,第二种方案中确定某个重复声明的属性的查询 顺序,可以通过规范语法进行确定,Python 提供了 mro() 方法用于确定继承关系中属性和方 法的查询操作顺序

class Animal:
    """动物类型"""
    def love(self):
        print("动物的爱")

class Person:
    """人的类型"""
    def love(self):
        print("人的爱")

class Tom(Animal,Person):
    pass


user_Tom = Tom()
user_Tom.love()
print(Tom.mro())

在这里插入图片描述
3、属性查询顺序
Python3 中已经改善了 Python2 中多种类型操作方式(Python2/3 的区别在十五讲会详细 说明),统一了类型的声明和加载方式,对于多继承中的重名属性和重名方法的查询执行顺 序,使用了广度优先的查询原则
在这里插入图片描述
(六)___init()___

这边其实方法重写已经提到过了
所以这边就简单复述下

  • 继__init() __构建对象后属性初始化的方法
  • 双下划线开头结尾称为魔法方法
  • 魔法方法只会继 承固定语法格式,如果在子类中改变了原有的语法格式的情况下,一定要主动调用父类相同 的方法初始化,否则会出现父类数据没有初始化的问题

如果子类中没有编写__init__()方法,创建对象时就会自动执行继承的默认的无参数的 init()方法,并且自动调用父类的__init__()完成初始化过程,如果所示:
在这里插入图片描述
如果子类中一旦编写了自定义了__init__()方法,默认继承的空参数的__init__()就会失效, 必须显式的主动的调用父类的__init__()方法完成父类初始化工作,否则父类的数据就不会被 正确的继承过来了
在这里插入图片描述

返回文章目录

三、多态

(一)什么是多态?
多态是程序运行过程中,根据运行时的数据的差异,产生不同的处理状态,运行不同的 逻辑代码的过程 多态作为面向对象的特征之一,没有固定的语法,在经典的程序设计模式中有多种体现 方式,如策略模式中就可以根据传递的具体执行方案执行对应的处理结果

多态基本案例:

# 定义人类:可以调速,可以玩,在玩的过程中跳舞
# 实现多态:老年人跳广场舞
# 多态三个条件
"""
    1.必须存在继承关系
    2.重写目标方法
    3.使用子类对象调用父类方法
"""

class Person:
    """人的类型"""

    def danc(self):
        print("跳舞")

    def play(self): #  self = old 老年人
        self.danc()# 老年人调用跳舞,本人含义跳舞


class OldMan(Person):
    """老年人类型"""
    def danc(self):
        print("跳广场舞")
#
# # per1 = Person()
# # per1.play()
old = OldMan()
old.play()



策略模式
在这里插入图片描述
图示中用户需要在某网站上注册账号,网站动态判断用户的注册方式并响应验证 码给正确的终端设备,在开发过程中函数式编程可以直接进行判断处理,但是不利于程序功 能的扩展(大家可以编写函数式的实现方式进行尝试)。通过策略模式进行完成上述功能流程, 同时还为将来功能的扩展预留了空间

"""
    网站可以注册,注册有默认的验证码发送方式
    分析:
        网站类
            方法:注册方法,调用默认设备,发送验证码
        设备类
            方法:生成验证码并发送

    策略模式

"""

class WebSite:
    """网站类型"""

    def register(self,device):
        print("开始注册")

        #调用设备发送验证码的方法
        device.send("6666")
        input("验证码已发送,请输入")
        print("注册成功")

class Device:
    """设备类型"""

    def send(self,code):
        print("默认发送验证码:",code)


class Phone(Device):
    """手机注册"""

    def send(self,code):
        print("通过手机发送验证码: ",code)

class Email(Device):
    """邮箱注册"""

    def send(self, code):
        print("通过手机发送验证码: ", code)

# 1 网页注册
# # 用户注册
# ws = WebSite()
# device = Device()
# # 发起注册
# ws.register(device)

# 2 手机注册
# 用户注册
ws = WebSite() # 创建对象
phone = Phone() # 实例化设备对象
# 发起注册
ws.register(phone)


在这里插入图片描述

返回文章目录

四、综合案例

"""
学生选课管理系统
    管理员,添加课程,查看课程 [,删除课程,修改课程]

    宗澄:课程保存课程说不通
    业务受理:增加课程,,管理员增加课程   add_course()
    逻辑处理:增删改查数据-- 保存数据-- 课程对象~保存自己的数据 save()
"""


class Database:
    """数据库类型:存储项目中的所有数据"""
    # 类属性:存储课程-- key课程名称:value课程对象
    courses_dict = dict()


class Users:
    """学生选课管理系统 用户类型"""

    def __init__(self, username, password, nickname, email, phone):
        """初始化属性数据"""
        self.username = username
        self.password = password
        self.nickname = nickname
        self.email = email
        self.phone = phone


class Manager(Users):
    """管理员类型"""
    def add_course(self):
        """增加课程的方法"""
        name = input("请输入课程名称:")
        if name in Database.courses_dict:
            print("课程已经存在,请使用其他名称添加")
            return self.add_course()
        teacher = input("请输入授课老师:")
        maxsize = input("请输入人数上限:")
        times = input("请输入课程课时:")
        score = input("请输入课程学分:")
        desc = input("请输入课程描述:")
        # 创建课程对象
        course = Course(name, teacher, maxsize, times, score, desc)
        # 保存课程数据
        course.save()
        input("课程添加完成,按任意键继续。")

    def check_course(self):
        """查询课程的方法"""
        # TODO 待完善
        for name, course in Database.courses_dict.items():
            print(f"课程名称:{name}, 课程:{course}")
        input("课程查看完成,按任意键继续")

    def update_course(self):
        """修改课程信息的方法"""
        name = input("请输入课程名称:")
        if name not in Database.courses_dict:
            print("课程不存在,请重新输入")
            return self.update_course()
        # 获取到要修改的课程数据
        course = Database.courses_dict.get(name)
        # 修改数据
        teacher = input("请输入授课老师:")
        maxsize = input("请输入人数上限:")
        times = input("请输入课程课时:")
        score = input("请输入课程学分:")
        desc = input("请输入课程描述:")
        # 保存课程数据
        course.update()
        input("课程修改完成,按任意键继续。")

    def delete_course(self):
        """删除课程的方法"""
        name = input("请输入要删除的课程名称:")
        if name not in Database.courses_dict:
            print("要删除的课程不存在,按任意键重新输入")
            return self.delete_course()
        # 直接删除课程:直接从字典中根据课程key删除了键值对
        Database.courses_dict.pop(name)
        input("课程删除完成,按任意键继续。")


class Course:
    """课程类型"""

    def __init__(self, name, teacher, maxsize, times, score, desc):
        self.name = name  # 课程名称
        self.teacher = teacher  # 授课老师
        self.maxsize = maxsize  # 选择人数限制
        self.times = times  # 授课课时
        self.score = score  # 课程学分
        self.desc = desc  # 课程描述

    def save(self):
        """保存课程数据"""
        Database.courses_dict[self.name] = self

    def update(self):
        """修改课程数据"""
        # 重新保存数据时,因为key没有变化,所以新的数据会覆盖旧的数据
        self.save()

    def delete(self):
        """删除课程"""
        # 通过key删除字典中的一个键值对
        Database.courses_dict.pop(self.name)

    def __str__(self):
        return f"课程[名称:{self.name}, 老师:{self.teacher},描述:{self.desc}]"


# 创建管理员对象
manager = Manager("wenwen", "123", "稳稳", "123456@offcn.com", "15666666666")
# 添加课程
manager.add_course()

# 查看课程
manager.check_course()



返回文章目录

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值