• Python基础之面向对象2(封装)


    一、封装定义:

      

     二、作用

      

    三、私有成员:

      1、基本概念及作用

        

      2、__slots__手段私有成员:

        

      3、@property属性手段私有成员:

        

    四、基础示例代码

      1、用方法封装变量

        

    """
        练习:用方法封装变量
    """
    class Enemy:
        def __init__(self,name,atk,speed,hp):
            self.set_name(name)
            self.set_atk(atk)
            self.set_atk_speed(speed)
            self.set_hp(hp)
    
        def get_name(self):
            return self.__name
    
        def set_name(self,value):
            self.__name = value
    
        def get_atk(self):
            return self.__atk
    
        def set_atk(self, value):
            self.__atk = value
    
        def get_atk_speed(self):
            return self.__atk_speed
    
        def set_atk_speed(self, value):
            if 0 <= value <= 10:
                self.__atk_speed = value
            else:
                self.__atk_speed = 0
                print("速度不再范围内,赋值失败")
    
        def get_hp(self):
            return self.__hp
    
        def set_hp(self, value):
            if 0 <= value <= 100:
                self.__hp = value
            else:
                self.__hp = 0
                print("血量不再范围内,赋值失败")
    
    
    e01 = Enemy("zs",200,50,200)
    print(e01.get_name(),e01.get_hp(),e01.get_atk_speed())

       2、用属性封装变量:

        

    """
        练习:属性封装变量
    """
    
    
    class Enemy:
        def __init__(self, name, atk, speed, hp):
            self.name = name
            self.atk = atk
            self.speed = speed
            self.hp = hp
    
        @property
        def name(self):
            return self.__name
    
        @name.setter
        def name(self,value):
            self.__name = value
    
        @property
        def atk(self):
            return self.__atk
    
        @atk.setter
        def atk(self, value):
            self.__atk = value
    
        @property
        def speed(self):
            return self.__speed
    
        @speed.setter
        def speed(self, value):
            self.__speed = value
    
        @property
        def hp(self):
            return self.__hp
    
        @hp.setter
        def hp(self, value):
            self.__hp= value
    
    
    e01 = Enemy("zs", 200, 50, 200)
    print(e01.name, e01.hp, e01.speed)

        3、基础代码1

        

    """
        封装数据优势:
         1.符合人类思考方式
         2.将数据与对数据的操作封装起来。
    
         使用方法封装变量
    """
    
    
    class Wife01:
        def __init__(self, name, age):
            self.name = name
            # 缺点:缺乏对象数据的封装,外界可以随意赋值.
            self.age = age
    
    
    w01 = Wife01("芳芳", 26)
    w02 = Wife01("铁锤", 86)
    w02.age = 87
    # print(w02.age)
    
    # 注意:通过两个方法,读写私有变量.
    # 练习:定义敌人类(姓名,攻击力,攻击速度(0-10),血量(0--100))
    class Wife02:
        def __init__(self, name = "", age = 0):
            self.set_name(name)
            # 私有成员:障眼法(解释器会改变双下划线开头的变量名)
            # self.__age = age
            self.set_age(age)
    
        def get_name(self):
            return self.__name
    
        def set_name(self,value):
            self.__name = value
    
        def get_age(self):
            return self.__age
    
        def set_age(self,value):
            if 20 <= value <= 30:
                self.__age = value
            else:
                print("我不要")
    
    w01 = Wife02("铁锤",86)
    # 找不到双下划线开头的数据
    # print(w01.__age)
    # 通过下划线 + 类名 可以访问双下划线开头的数据
    # print(w01._Wife02__age)
    w01.set_age(50)
    print(w01.get_age())
    print(w01.__dict__)

        4、基础代码2:

        

    """
        使用属性封装变量
    """
    
    # 练习:修改Enemy类,使用属性封装变量
    class Wife:
        def __init__(self, name="", age=0):
            self.name = name  # 调用 @name.setter 修饰的方法
            self.age = age  # 调用 @age.setter 修饰的方法
    
        @property  # 拦截读取变量的操作
        def name(self):  # get_name()
            return self.__name
    
        @name.setter  # 拦截写入变量的操作
        def name(self, value):  # set_name()
            self.__name = value
    
        @property
        def age(self):
            return self.__age
    
        @age.setter
        def age(self, value):
            if 20 <= value <= 30:
                self.__age = value
            else:
                self.__age = 0
                print("我不要")
    
    
    w01 = Wife("铁锤", 86)
    print(w01.name)
    print(w01.age)

      5、基础代码3:

        

    """
        __slots__ 属性
    """
    class SkillData:
        # 限制当前类,创建的对象,只能具有的实例变量.
        __slots__ = ("__name")
    
        def __init__(self, name):
            self.name = name
    
        @property
        def name(self):
            return self.__name
    
        @name.setter
        def name(self, value):
            self.__name = value
    
    
    s01 = SkillData("技能名称")
    # s01.name = "降龙十八掌"
    print(s01.name)
    # 为当前对象,添加实例变量
    # s01.time = 5
    # print(s01.time)
    # print(s01.__dict__) # 因为使用了__slots__属性,所以不是使用__dict__.

       6、基础代码4:

       

    """
        需求: 老张开去车东北.
        分而治之 -- 分解
               变化点
        练习:exercise01
    """
    
    #需求: 老张开去车东北.
    class Person:
        def __init__(self, name):
            self.name = name
    
        def go_to(self, type, str_pos):
            type.run(str_pos)
    
    class Car:
        def run(self, str_pos):
            print("行驶到", str_pos)
    
    p01 = Person("老张")
    c01 = Car()
    p01.go_to(c01, "东北")

    五、实例练习:

       练习1:

        

    """
        以面向对象的思想,描述下列场景.
        提示:对象与对象数据不同,类与类行为不同.
      张三 教 李四 学习python
       李四  教 张三  玩游戏
       张三 工作 挣了8000元
       李四 工作 挣了3000元
    """
    
    class Person:
        def __init__(self, name):
            # 人的姓名
            self.name = name
            # 人会的所有技能
            self.__skills = []
            self.__total_money = 0
    
        # 只读属性
        @property
        def skills(self):
            # return self.__skills # 返回可变对象地址,意味着类外仍然可以操作可变对象
            return self.__skills[:] # 返回新的可变对象地址,意味着类外仍然操作的是新可变对象,不影响原对象.
            # 备注:每次通过切片返回新对象,都会另外开辟空间创建新对象,占用过多内存.
    
        # 只读属性
        @property
        def total_money(self):
            return self.__total_money
    
    
        @property
        def name(self):
            return self.__name
    
        @name.setter
        def name(self,value):
            self.__name = value
    
    
        def teach(self, person_other, str_skill):
            # person_other 的技能列表,增加str_skill
            person_other.__skills.append(str_skill)
            print(self.name, "教了", person_other.name, str_skill)
    
        def work(self, money):
            self.__total_money += money
            print(self.name, "工作挣了", money, "")
    
    
    zs = Person("张三")
    ls = Person("李四")
    # 张三 教 李四 学习python
    zs.teach(ls, "python")
    # 李四  教 张三  玩游戏
    ls.teach(zs, "游戏")
    
    zs.work(8000)
    ls.work(4000)
    
    #************************
    zs = Person("张三")
    # zs.skills = [] # 不能改
    # 如果skills属性,返回的是__skills,那么仍然可以操作私有列表
    #                     __skills[:],那么操作的是新列表
    zs.skills.append("python")
    print(zs.skills)

        练习2:

        

    """
        创建技能类(技能名称,冷却时间,持续时间,攻击距离......)
        要求:使用属性封装变量
       创建技能列表(技能对象的列表)
       -- 查找名称是"降龙十八掌"的技能对象
       -- 查找名称是持续时间大于10秒的的所有技能对象
       -- 查找攻击距离最远的技能对象
       -- 按照持续时间,对列表升序排列.
    """
    
    
    class SkillData:
        def __init__(self, name, cd, time, distance):
            self.name = name
            self.cd = cd
            self.time = time
            self.atk_distance = distance
    
        @property
        def name(self):
            return self.__name
    
        @name.setter
        def name(self, value):
            self.__name = value
    
        @property
        def cd(self):
            return self.__cd
    
        @cd.setter
        def cd(self, value):
            self.__cd = value
    
        @property
        def time(self):
            return self.__time
    
        @time.setter
        def time(self, value):
            self.__time = value
    
        @property
        def atk_distance(self):
            return self.__atk_distance
    
        @atk_distance.setter
        def atk_distance(self, value):
            self.__atk_distance = value
    
        def print_self(self):
            print(self.name, self.cd, self.time, self.atk_distance)
    
    
    list_skills = [
        SkillData("降龙十八掌", 60, 10, 5),
        SkillData("如来神掌", 50, 5, 15),
        SkillData("六脉神剑", 80, 20, 8),
        SkillData("一阳指", 20, 50, 15),
        SkillData("冷酷追击", 15, 30, 9),
    ]
    
    # -- 查找名称是"降龙十八掌"的技能对象
    for item in list_skills:
        if item.name == "降龙十八掌":
            item.print_self()
    
    # -- 查找名称是持续时间大于10秒的的所有技能对象
    result = []
    for item in list_skills:
        if item.time > 10:
            result.append(item)
    
    # -- 查找攻击距离最远的技能对象
    result = list_skills[0]
    for i in range(1, len(list_skills)):
        # 后面的技能对象
        if result.atk_distance < list_skills[i].atk_distance:
            result = list_skills[i]
            # result.atk_distance = list_skills[i].atk_distance
    
    result.print_self()
    
    # -- 按照持续时间,对列表升序排列.
    for r in range(len(list_skills) - 1):
        for c in range(r + 1, len(list_skills)):
            if list_skills[r].time  >  list_skills[c].time:
                list_skills[r],list_skills[c] =  list_skills[c],list_skills[r]
    
    
    # 请用调试,查看列表的取值.
    print(list_skills)

        练习3:

        

    # 练习: 小明在招商银行取钱.
    class Person:
        def __init__(self, name, money=0):
            self.name = name
            self.money = money
    
    class Bank:
        def __init__(self, name, money):
            self.name = name
            self.total_money = money
    
        # 考虑:取钱逻辑,应该由银行决定.所以取钱方法,定义在了银行.
        def draw_money(self, person, value):
            if self.total_money >= value:
                self.total_money -= value
                person.money += value
                print(person.name, "取钱成功")
            else:
                print("取钱失败")
    
    p01 = Person("小明")
    b01 = Bank("招商银行", 100000)
    b01.draw_money(p01, 10000000)

        练习4

        

    """
        学生管理器系统
    """
    
    
    class StudentModel:
        """
            学生数据模型类
        """
    
        def __init__(self, name="", age=0, score=0, id=0):
            """
                创建学生对象
            :param id: 编号
            :param name: 姓名
            :param age: 年龄
            :param score: 成绩
            """
            self.id = id
            self.name = name
            self.age = age
            self.score = score
    
        @property
        def id(self):
            return self.__id
    
        @id.setter
        def id(self, value):
            self.__id = value
    
        @property
        def name(self):
            return self.__name
    
        @name.setter
        def name(self, value):
            self.__name = value
    
        @property
        def age(self):
            return self.__age
    
        @age.setter
        def age(self, value):
            self.__age = value
    
        @property
        def score(self):
            return self.__score
    
        @score.setter
        def score(self, value):
            self.__score = value
    
    
    class StudentManagerController:
        """
            学生逻辑控制器
        """
    
        def __init__(self):
            self.__list_stu = []
    
        @property
        def list_stu(self):
            return self.__list_stu
    
        def add_student(self, stu):
            """
                添加新学生
            :param stu: 需要添加的学生对象
            """
            stu.id = self.__generate_id()
            self.__list_stu.append(stu)
    
        def __generate_id(self):
            # 生成编号的需求:新编号,比上次添加的对象编号多1.
            # if len(self.__list_stu) > 0:
            #     id = self.__list_stu[-1].id + 1
            # else:
            #     id = 1
            # return id
            return self.__list_stu[-1].id + 1 if len(self.__list_stu) > 0 else 1
    
    
    # controller = StudentManagerController()
    # controller.add_student(StudentModel("zs",18,85))
    # controller.add_student(StudentModel("zs",18,85))
    # for item in controller.list_stu:
    #     print(item.id,item.name,item.age,item.score)
    
    class StudentManagerView:
        """
            界面视图类
        """
        def __init__(self):
            # 创建逻辑控制器对象
            self.__manager = StudentManagerController()
    
        def __input_students(self):
            # 1. 在控制台中录入学生信息,存成学生对象StudentModel.
            stu = StudentModel()
            stu.name = input("请输入姓名:")
            stu.age = int(input("请输入年龄:"))
            stu.score = int(input("请输入成绩:"))
            # 2. 调用逻辑控制器的add_student方法
            self.__manager.add_student(stu)
            print(self.__manager)
    
    
        def __display_menu(self):
            """
                显示菜单
            :return:
            """
            print("1) 添加学生")
            print("2) 显示学生")
            print("3) 删除学生")
            print("4) 修改学生")
            print("5) 按照成绩降序排列")
    
        def __select_menu(self):
            """
            选择菜单
            :return:
            """
            number = input("请输入选项:")
            if number == "1":
                self.__input_students()
            elif number == "2":
                pass
            elif number == "3":
                pass
            elif number == "4":
                pass
            elif number == "5":
                pass
    
        def main(self):
            """
                界面入口方法
            :return:
            """
            while True:
                self.__display_menu()
                self.__select_menu()
    
    
    view = StudentManagerView()
    view.main()

        内存图如下:

        

       练习5

        

    # 1. 使用面向对象思想,写出下列场景:
    #     玩家(攻击力)攻击敌人,敌人受伤(血量)后掉血,还可能死亡(播放动画).
    #     敌人(攻击力)攻击力攻击玩家,玩家(血量)受伤后碎屏,还可能死亡(游戏结束).
    # 程序调试,画出内存图.
    
    class Player:
        """
            玩家类
        """
        def __init__(self,hp,atk):
            self.atk = atk
            self.hp = hp
    
        def attack(self,enemy):
            print("打死你")
            # 调用敌人受伤方法(敌人负责定义受伤逻辑)
            enemy.damage(self.atk)
    
        def damage(self,value):
            self.hp -= value
            print("玩家受伤啦,屏幕碎啦")
            if self.hp <= 0:
                self.__death()
    
        def __death(self):
            print("玩家死亡,游戏结束")
    
    
    class Enemy:
        def __init__(self,hp,atk):
            self.hp = hp
            self.atk = atk
    
        def damage(self,value):
            self.hp -= value
            print("受伤啦")
            if self.hp <= 0:
                self.__death()
    
        def attack(self,player):
            print("打死你")
            player.damage(self.atk)
    
        def __death(self):
            print("死啦,播放动画")
    
    
    p01 = Player(100,50)
    e01 = Enemy(60,10)
    # 玩家打敌人
    p01.attack(e01)
    # p01.attack(e01)
    e01.attack(p01)

        内存图如下:

        

        

  • 相关阅读:
    linux之sed用法【转载】
    关于Cookie和Session【转载】
    Oracle分页查询与RowNum
    fstream的用法
    Java:Date、Calendar、Timestamp的区别、相互转换与使用【转载】
    DatabaseMetaData的用法【转载】
    关于SQL的Group By
    【转载】B树、B-树、B+树、B*树都是什么
    Spring的MVC控制器返回ModelMap时,会跳转到什么页面?
    关于jsp中超链接的相对路径
  • 原文地址:https://www.cnblogs.com/yuxiangyang/p/10712430.html
Copyright © 2020-2023  润新知