pt05Encapsulationinherit
Encapsulation &inherit 封装继承
封装
向类外提供必要的功能,隐藏实现的细节, 代码可读性更高优势:简化编程,使用者不必了解具体的实现细节,只需要调用对外提供的功能。私有成员:作用:无需向类外提供的成员,可以通过私有化进行屏蔽。做法:命名使用双下划线开头。本质:障眼法,实际也可以访问。私有成员的名称被修改为:类名.__成员名,可以通过__dict__属性查看。
私有化:以双下划线开头
"""私有化作用:类中成员,在类外无法访问语法:命名: 以双下划线开头本质:障眼法看上去是私有变量名 __data实际上是:单下划线+类名+私有变量名 _MyClass__data
"""class MyClass:def __init__(self):# 私有的实例变量self.__data = 10# 私有的方法def __func01(self):print(self.__data)def func02(self):# 公开方法,可以访问私有成员print(self.__data)self.__func01()m = MyClass()
print(m.__dict__) # {'_MyClass__data': 10}
print(m._MyClass__data) #10 私有变量名__data,实际上调用是_MyClass__data,前提是你知道这么多信息print(m.__data) # 不能直接访问私有成员,报错
m.__func01() # 不能直接访问私有成员,报错
m.func02() # 只能访问公开成员 10 \n 10
shift+F6 批量更改 refactor,do refactor
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u2Xo9dNs-1680706395708)(picture\26235120.png)]
练习
"""学生信息管理系统MVC练习1:将商品控制器的开始编号,由实例变量改为类变量(即使有多个控制器,也能操作一个开始编号,实现编号唯一)练习2:封装商品信息管理系统尽量隐藏V与C中不对外提供的成员练习3:将商品信息管理系统中C的列表改为只读属性
"""class StudentModel:def __init__(self, name="", age=0, score=0.0, sid=0):self.name = nameself.age = ageself.score = score# 由系统决定的全球唯一标识符(不是用户输入的)self.sid = sidclass StudentView:"""学生视图:输入/输出学生信息"""def __init__(self):self.__controller = StudentController()def __display_menu(self):print("按1键录入学生信息")print("按2键显示学生信息")print("按3键删除学生信息")print("按4键修改学生信息")print("按5键根据成绩显示学生信息")def __select_menu(self):item = input("请输入选项:")if item == "1":self.__input_student()elif item == "2":# 先写出调用函数代码,再快捷键生成定义函数代码# alt + 回车self.__display_students()elif item == "3":self.__delete_student()elif item == "4":self.__set_student()elif item == "5":self.__order_by_score()def __input_student(self):stu = StudentModel()stu.name = input("请输入学生姓名:")stu.age = int(input("请输入学生年龄:"))stu.score = int(input("请输入学生成绩:"))self.__controller.add_student(stu)def main(self):while True:self.__display_menu()self.__select_menu()def __display_students(self):for item in self.__controller.list_student:print(f"{item.name}的编号是{item.sid},年龄是{item.age},成绩是{item.score}")def __delete_student(self):sid = int(input("请输入需要删除的学生编号:"))if self.__controller.remove_student(sid):print("删除成功")else:print("删除失败")def __set_student(self):stu = StudentModel()stu.sid = input("请输入学生编号:")stu.name = input("请输入学生姓名:")stu.age = int(input("请输入学生年龄:"))stu.score = int(input("请输入学生成绩:"))if self.__controller.update_student(stu):print("修改成功")else:print("修改失败")def __order_by_score(self):self.__controller.ascending_order()self.__display_students()class StudentController:"""学生控制器:处理核心功能,存储..."""__start_id = 100 # 大家的:系统不同界面使用的学生编号是一份(连续增加)@classmethoddef __set_student_id(cls, stu):cls.__start_id += 1stu.sid = cls.__start_iddef __init__(self):self.__list_student = [] # 自己的:系统不同界面使用自己数据(可以显示不同数据)@property # 只读属性:View类只能读取,不能修改def list_student(self):return self.__list_studentdef add_student(self, new_stu):# 设置学生编号StudentController.__set_student_id(new_stu)# 追加到列表中self.__list_student.append(new_stu)def remove_student(self, sid):"""在列表中删除学生信息:param sid: 学生编号:return: 是否成功"""for i in range(len(self.__list_student)):if self.__list_student[i].sid == sid:del self.__list_student[i]return True # 删除成功return False # 删除失败def update_student(self, stu):""":param stu::return:"""for i in range(len(self.__list_student)):if self.__list_student[i].sid == stu.sid:# self.list_student[i].name = stu.name# self.list_student[i].age = stu.age# self.list_student[i].score = stu.scoreself.__list_student[i].__dict__ = stu.__dict__return Truereturn Falsedef ascending_order(self):for r in range(len(self.__list_student) - 1):for c in range(r + 1, len(self.__list_student)):if self.__list_student[r].score > self.__list_student[c].score:self.__list_student[r], self.__list_student[c] = self.__list_student[c], self.__list_student[r]# 入口
view = StudentView()
view.main() #view.时,别的都不显示了
练习
"""属性-原理作用:对实例变量进行有效性验证练习: 创建敌人类,并保护数据在有效范围内数据:姓名、攻击力、血量0-100 0-500
"""
# 需求:限制age在有效范围之内 20~30
# 步骤:
# 1. 私有化实例变量
# 2. 提供公开的读写方法
class Wife:def __init__(self, name="", age=0):self.name = name# self.__age = age #私有化,注释掉不调用,走下面的set_ageself.set_age(age) #调用下面def set_age(self, value):if value > 30:value = 30elif value < 20:value = 20self.__age = value #不能直接调,必须走set_age,过条件设置def get_age(self):return self.__ageshuang_er = Wife("双儿", 260)
# shuang_er.age = 350
shuang_er.set_age(350)
print(shuang_er.name)
# print(shuang_er.age)
print(shuang_er.get_age()) # debug下看过程
练习: 创建敌人类,并保护数据在有效范围内 原理了解
"""练习: 创建敌人类,并保护数据在有效范围内数据:姓名、攻击力、血量0-100 0-500
"""class Enemy:def __init__(self, name="", atk=0, hp=0):self.name = name# self.__atk = atkself.set_atk(atk)self.set_hp(hp)def set_atk(self, value):if value < 0:value = 0elif value > 100:value = 100self.__atk = valuedef get_atk(self):return self.__atkdef set_hp(self, value):if value > 500:value = 500elif value < 0:value = 0self.__hp = valuedef get_hp(self):return self.__hpmie_ba = Enemy("灭霸", 100, 50000000)
print(mie_ba.name)
# print(mie_ba.atk)
print(mie_ba.get_atk())
# print(mie_ba.hp)
print(mie_ba.get_hp())
过度版本(了解)
"""属性 property - 过度属性就是包装了读取函数与写入函数的对象
"""class Wife:def __init__(self, name="", age=0):self.name = name# self.set_age(age)self.age = age #调用下面创建属性对象agedef set_age(self, value):if value > 30:value = 30elif value < 20:value = 20self.__age = valuedef get_age(self):return self.__age# 创建属性对象(读取函数,写入函数)age = property(get_age, set_age) #连接上面两个函数shuang_er = Wife("双儿", 260)
shuang_er.age = 350 #debug看过程
# shuang_er.set_age(350)
print(shuang_er.name)
print(shuang_er.age)
# print(shuang_er.get_age())
属性 :保护实例变量
标准属性书写
"""属性 property - 标准属性保护实例变量属性中操作的是私有变量
"""class Wife:def __init__(self, name="", age=0):self.name = nameself.age = age@property # age = property( age )def age(self):return self.__age@age.setter # age = age.setter( age )def age(self, value):if value > 30:value = 30elif value < 20:value = 20self.__age = valueshuang_er = Wife("双儿", 260)
print(shuang_er.__dict__)
shuang_er.age = 350
print(shuang_er.name)
print(shuang_er.age)
练习
"""练习: 创建敌人类,并保护数据在有效范围内数据:姓名、攻击力、血量
0-100 0-500
"""class Enemy:def __init__(self, name="", atk=0, hp=0):self.name = nameself.atk = atkself.hp = hp@propertydef atk(self):return self.__atk@atk.setterdef atk(self, value):if value < 0:value = 0elif value > 100:value = 100self.__atk = value@propertydef hp(self):return self.__hp@hp.setterdef hp(self, value):if value < 0:value = 0elif value > 500:value = 500self.__hp = valuemie_ba = Enemy("灭霸", 100, 50000000)
print(mie_ba.name)
print(mie_ba.atk)
print(mie_ba.hp)
读写、只读、只写属性写法
"""属性各种写法"""# 1. 读写属性: 对读取和写入过程进行逻辑处理
# 快捷键: 输入props + 回车
class MyClass:def __init__(self, data=""):self.data = data@propertydef data(self):return self.__data@data.setterdef data(self, value):self.__data = valuem = MyClass("数据")
print(m.data)# 2. 只读属性: 对私有变量,向类外提供读取操作
# 快捷键: prop + 回车
class MyClass:def __init__(self):self.__data = "数据" #对私有变量,向类外提供读取操作@propertydef data(self):return self.__datam = MyClass()# m.data = "新数据" # AttributeError: can't set attribute
print(m.data)# 3. 只写属性:使用较少,只能修改,不能读取.
# 快捷键:无
class MyClass:def __init__(self, data=""):self.data = data# @property # data = property( data )# def data(self):# return self.__data# 写法1:# data = property()## @data.setter# def data(self, value):# self.__data = value# 写法2: def data(self, value):self.__data = valuedata = property(fset=data)m = MyClass("数据")
# print(m.data) # AttributeError: unreadable attribute
m.data = "新数据"
print(m.__dict__)
练习
"""练习2:创建技能类,并保护数据在有效范围内数据:技能名称、冷却时间、攻击力度、消耗法力
0 -- 120 0 -- 200 100 -- 100
"""class Skill:def __init__(self, name="", cooling_time=0, atk=0):self.name = nameself.cooling_time = cooling_timeself.atk = atkself.__cost_sp = 100@propertydef cooling_time(self):return self.__cooling_time@cooling_time.setterdef cooling_time(self, value):if value < 0: value = 0if value > 120: value = 120self.__cooling_time = value@propertydef atk(self):return self.__atk@atk.setterdef atk(self, value):if value < 0: value = 0if value > 200: value = 200self.__atk = value@propertydef cost_sp(self):return self.__cost_spslsbz = Skill("降龙十八掌", 100, 100)
print(slsbz.__dict__)
练习
"""创建桌子类,保护数据在有效范围内数据:品牌, 材质, 尺寸(120,60,80)[实木,板材,金属]其中之一 长度为3"""class Desk:def __init__(self, brand="", material="", size=()):self.brand = brandself.material = materialself.size = size@property # 函数 = property(函数)def material(self):return self.__material@material.setter # 函数 = material.setter(函数)def material(self, value):if value in ("实木", "板材", "金属"):self.__material = valueelse:self.__material = "实木"@propertydef size(self):return self.__size@size.setterdef size(self, value):if len(value) == 3:self.__size = valueelse:self.__size = (120, 60, 80)lege = Desk("乐歌", "金属", (112, 29.5, 16))
print(lege.brand)
print(lege.material)
print(lege.size)
print(lege.__dict__)
继承
继承方法
继承 - 行为皇位:江山不用太子打,但是可以直接坐编程:代码不用子类写,但是可以直接用class 父类:def 父类方法(self):方法体class 子类(父类):def 子类方法(self):方法体儿子 = 子类()
儿子.子类方法()
儿子.父类方法() #子类直接拥有父类的方法.
内置函数
(1) isinstance(对象, 类型) 返回指定对象是否是某个类的对象。
(2) issubclass(类型,类型) 返回指定类型是否属于某个类型。
演示
# 多个类型在概念上是统一的,在成员上有重复.
# def say(self) 重复class Student:def say(self):print("说话")def play(self):print("玩耍")class Teacher:def say(self):print("说话")def teach(self):print("教学")
class Person:def say(self):print("说话")class Student(Person):def play(self):print("玩耍")self.say()class Teacher(Person):def teach(self):print("教学")# 子类既可以访问自己成员,也可以访问父类成员(不劳而获)
qtx = Teacher()
qtx.say()
qtx.teach()# 父类只能访问自己的成员
zs = Person()
zs.say()
关系判定
# 1.对象是一种类型
# 老师对象是一种老师类型
print(isinstance(qtx, Teacher)) # True
# 老师对象是一种人类型
print(isinstance(qtx, Person)) # True
# 人对象是一种老师类型
print(isinstance(zs, Teacher)) # False
# 老师对象是一种学生类型
print(isinstance(qtx, Student)) # False# 2.类型是一种类型
# 老师类型是一种老师类型
print(issubclass(Teacher, Teacher)) # True
# 老师类型是一种人类型
print(issubclass(Teacher, Person)) # True
# 人类型是一种老师类型
print(issubclass(Person, Teacher)) # False
# 老师类型是一种学生类型
print(issubclass(Teacher, Student)) # False# 3. 对象是类型
# 老师对象是老师类型
print(type(qtx) == Teacher) # True
# 老师对象是人类型
print(type(qtx) == Person) # False
# 人对象是老师类型
print(type(zs) == Teacher) # False
# 老师对象是学生类型
print(type(qtx) == Student) # False
练习
""创建子类:狗(跑),鸟类(飞)创建父类:动物(吃)体会子类复用父类方法体会 isinstance 、issubclass 与 type 的作用.
"""class Animal:def eat(self):print("吃")class Dog(Animal):def run(self):self.eat()print("跑")class Bird(Animal):def fly(self):print("飞")a01 = Animal()
d01 = Dog()
b01 = Bird()d01.run() # 吃 \n 跑
d01.eat() # 吃# 类型 与 类型 的关系
print(issubclass(Animal, Dog)) # False# 对象 与 类型 的关系
print(isinstance(b01, Animal)) # True# 狗对象 与 动物类型 相同
print(type(d01) == Animal) # False
继承数据
class 子类(父类):def __init__(self,父类参数,子类参数):super().__init__(参数) # 调用父类构造函数self.实例变量 = 参数
"""继承数据
"""
# 1. 子类如果没有构造函数,直接使用父类构造函数.
class Person:def __init__(self, name="", age=0):self.name = nameself.age = ageclass Student(Person):passzs = Student("张三", 26)
print(zs.__dict__)# 2. 子类如果有构造函数,会覆盖父类构造函数,好像他不存在.class Student(Person):def __init__(self, score=0):self.score = score
zs = Student(100)
print(zs.__dict__) #{'score': 100}# 此时必须通过super()函数调用父类构造函数
class Student(Person): # 注意:子类构造函数参数:父类+子类def __init__(self, name="", age=0, score=0):super().__init__(name, age)#debug,到此会调上面的person类创建name、age,再创建自己的scoreself.score = scorezs = Student(100)
print(zs.__dict__) # {'name': 100, 'age': 0, 'score': 0}zs = Student("张三", 26, 100)
print(zs.__dict__) #{'name': '张三', 'age': 26, 'score': 100}
练习
"""父类:车(品牌,速度)创建子类:电动车(电池容量,充电功率)
"""class Car:def __init__(self, brand, speed):self.brand = brandself.speed = speedclass ElectricCars(Car):# 1. 子类构造函数参数:父类参数+子类参数def __init__(self, brand, speed, battery_capacity, charging_power):# 2. 通过super调用父类构造函数super().__init__(brand, speed)self.battery_capacity = battery_capacityself.charging_power = charging_powerbc = Car("奔驰", 220)
print(bc.__dict__) #{'brand': '奔驰', 'speed': 220}am = ElectricCars("艾玛", 180, 10000, 220)
print(am.__dict__) #{'brand': '艾玛', 'speed': 180, 'battery_capacity': 10000, 'charging_power': 220}
定义了解
(1) 概念: 重用现有类的功能,并在此基础上进行扩展。
(2) 说明:子类直接具有父类的成员(共性),还可以扩展新功能。
(3) 相关知识父类(基类、超类)、子类(派生类)。父类相对于子类更抽象,范围更宽泛;子类相对于父类更具体,范围更狭小。单继承:父类只有一个(例如 Java,C#)。多继承:父类有多个(例如C++,Python)。Object类:任何类都直接或间接继承自 object 类。
多态
(1) 字面意思:对于一种行为有不同表现形态。
(2) 概念:对于父类的一个方法,在不同的子类上有不同体现。
(3) 说明:编码时调用父类方法,运行时传递子类对象执行子类方法。
重写
(1) 定义:在子类定义与父类相同的方法。
(2) 作用:改变父类行为,体现子类个性。
重写内置函数str
(1) 定义:Python中,以双下划线开头、双下划线结尾的是系统定义的成员。我们可以在自定义类中进
行重写,从而改变其行为。
(2) __str__ 函数:将对象转换为字符串(对人友好的)
"""重写内置函数重写:子类具有与父类名称相同的函数目的:改变其行为
"""
class Person(object):def __init__(self, name="", age=0):self.name = nameself.age = age
#zs = Person("张三",36)
#print(zs) #<__main__.Person object at 0x01C4E350>,直接打印的结果# 自定义对象转换-->字符串def __str__(self):return "姓名是zs,年龄是26"# 自定义对象-->整数# def __int__(self):# return self.agezs = Person("张三",36)
# <__main__.Person object at 0x7f03d5e76e80># 打印自定义对象时,会自动调用__str__
print(zs) #姓名是zs,年龄是26
练习:
"""直接打印商品对象: xx的编号是xx,单价是xx直接打印敌人对象: xx的攻击力是xx,血量是xx
"""class Commodity:def __init__(self, cid=0, name="", price=0):self.cid = cidself.name = nameself.price = price
#c01 = Commodity(1001, "屠龙刀", 10000)
#print(c01) #<__main__.Commodity object at 0x00EEE350>def __str__(self):return f"{self.name}的编号是{self.cid},单价是{self.price}"class Enemy:def __init__(self, name="", atk=0, hp=0):self.name = nameself.atk = atkself.hp = hpdef __str__(self):return "%s的攻击力是%d,血量是%d" % (self.name, self.atk, self.hp)c01 = Commodity(1001, "屠龙刀", 10000)
print(c01) # 自动调用__str__ 屠龙刀的编号是1001,单价是10000e01 = Enemy("灭霸")
print(e01) # 自动调用__str__ 灭霸的攻击力是0,血量是0
运算符重载(重写)
"""运算符重载(重写)算数运算符
"""
class Vector2:def __init__(self, x, y):self.x = xself.y = y# +def __add__(self, other):# print(type(qtx) == Teacher)if type(other) == Vector2: #判断是否是向量类型eg:(3,2)x = self.x + other.xy = self.y + other.yelse:x = self.x + othery = self.y + otherreturn Vector2(x, y)pos01 = Vector2(3, 2)
pos02 = Vector2(5, 3)
pos03 = pos01 + pos02 # pos01.__add__(pos02)
print(pos03.__dict__) #{'x': 8, 'y': 5}pos05 = pos01 + 6 # pos01.__add__(6) #6不是向量,pos01值都加6
print(pos05.__dict__) #{'x': 9, 'y': 8}
算数运算符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m9qwWSiy-1680706395709)(picture\328220422.png)]
复合运算符重载
"""练习:创建颜色类,数据包含r、g、b、a,实现颜色对象相加。
"""
class Color:def __init__(self, r, g, b, a):self.r = rself.g = gself.b = bself.a = adef __sub__(self, other):if type(other) == Color:r = c01.r - other.rg = c01.g - other.gb = c01.b - other.ba = c01.a - other.aelse:r = c01.r - otherg = c01.g - otherb = c01.b - othera = c01.a - otherreturn Color(r, g, b, a)c01 = Color(50, 0, 0, 200)
c02 = Color(0, 100, 0, 100)
c03 = c01 - c02 # c01.__sub__(c02)
print(c03.__dict__)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3SG9Y4qK-1680706395710)(picture\28222439.png)]
"""运算符重载(重写)增强运算符
"""
class Vector2:def __init__(self, x, y):self.x = xself.y = y# + 返回新数据def __add__(self, other):x = self.x + other.xy = self.y + other.yreturn Vector2(x, y)# += 返回旧数据def __iadd__(self, other):self.x += other.xself.y += other.yreturn selfpos01 = Vector2(3, 2)
pos02 = Vector2(5, 3)
print(id(pos01)) # 31122256
pos01 += pos02 # pos01.__iadd__(pos02)
print(id(pos01)) # 31122256
print(pos01.__dict__) #{'x': 8, 'y': 5}# 不可变数据的+=,在原有基础上改变
data01 = [10]
print(id(data01)) #15615480
data01 += [20]
print(id(data01)) #15615480
print(data01) #[10, 20]# 不可变数据的+=,创建了新数据
data01 = (10,)
print(id(data01)) # 26052048
data01 += (20,)
print(id(data01)) # 27950496
print(data01) #(10, 20)
"""练习:创建颜色类,数据包含r、g、b、a,实现颜色对象累加。
"""class Color:def __init__(self, r, g, b, a):self.r = rself.g = gself.b = bself.a = adef __imul__(self, other):self.r *= other.rself.g *= other.gself.b *= other.bself.a *= other.areturn selfc01 = Color(50, 0, 0, 200)
c02 = Color(0, 100, 0, 100)
c01 *= c02
print(c01.__dict__)
比较运算重写使用较多
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-peNMZGu0-1680706395711)(picture\328222845.png)]
"""运算符重载(重写)比较运算符
"""
"""
class Vector2:def __init__(self, x, y):self.x = xself.y = ypos01 = Vector2(3, 2)
pos02 = Vector2(3, 2)
print(pos01 == pos02) # False 需要重写__eq__list_data = [Vector2(1, 1),Vector2(3, 3),Vector2(2, 2),Vector2(5, 5),Vector2(4, 4),
]
print(Vector2(1, 1) in list_data) #False
list_data.remove(Vector2(3, 3)) #list.remove(x): x not in list
print(list_data) #[<__main__.Vector2 object at 0x013CED10>, <__main__.Vector2 object at 0x014B2530>, <__main__.Vector2 object at 0x014B23D0>, <__main__.Vector2 object at 0x014B2510>, <__main__.Vector2 object at 0x014B23F0>]
"""
###需要重写__eq__##########
class Vector2:def __init__(self, x, y):self.x = xself.y = y# 相同的依据def __eq__(self, other):# return self.x == other.x and self.y == other.yreturn self.__dict__ == other.__dict__# 大小的依据def __gt__(self, other):return self.x ** 2 + self.y ** 2 > other.x ** 2 + other.y ** 2# 1. 需要重写__eq__
pos01 = Vector2(3, 2)
pos02 = Vector2(3, 2)
print(pos01 == pos02) # True
list_data = [Vector2(1, 1),Vector2(3, 3),Vector2(2, 2),Vector2(5, 5),Vector2(4, 4),
]
print(Vector2(1, 1) in list_data) #True
list_data.remove(Vector2(3, 3))
print(list_data) #[<__main__.Vector2 object at 0x01F2ED10>, <__main__.Vector2 object at 0x02012510>, <__main__.Vector2 object at 0x020123F0>, <__main__.Vector2 object at 0x02012470>]value = max(list_data) #需要重新__gt__,向量大小看平方和
print(value.__dict__) #{'x': 5, 'y': 5}list_data.sort() # 升序排列
list_data.sort(reverse=True) # 降序排列
print(list_data) #[<__main__.Vector2 object at 0x020123F0>, <__main__.Vector2 object at 0x02012470>, <__main__.Vector2 object at 0x02012510>, <__main__.Vector2 object at 0x01F2ED10>]
"""练习:创建颜色列表,实现in、count、index、max、sort运算
"""class Color:def __init__(self, r, g, b, a):self.r = rself.g = gself.b = bself.a = adef __eq__(self, other):return self.__dict__ == other.__dict__def __gt__(self, other):return self.a > other.alist_data = [Color(1, 1, 1, 1),Color(2, 2, 2, 2),Color(4, 4, 4, 4),Color(3, 3, 3, 3),
]
print(Color(3, 3, 3, 3) in list_data) # 内部自动调用eqmax_value = max(list_data) # 内部自动调用gt
print(max_value.__dict__)
"""学生信息管理系统MVC练习:--在View直接打印商品 __str__--在Controller通过remove __eq__--在Controller通过sort排序__gt__
"""class StudentModel:def __init__(self, name="", age=0, score=0.0, sid=0):self.name = nameself.age = ageself.score = scoreself.sid = sid# 两个学生对象是否相同的依据:编号def __eq__(self, other):return self.sid == other.sid# 两个学生对象大小的依据:成绩def __gt__(self, other):return self.score > other.score# 显示学生的风格def __str__(self):return f"{self.name}的编号是{self.sid},年龄是{self.age},成绩是{self.score}"class StudentView:"""学生视图:输入/输出学生信息"""def __init__(self):self.__controller = StudentController()def __display_menu(self):print("按1键录入学生信息")print("按2键显示学生信息")print("按3键删除学生信息")print("按4键修改学生信息")print("按5键根据成绩显示学生信息")def __select_menu(self):item = input("请输入选项:")if item == "1":self.__input_student()elif item == "2":# 先写出调用函数代码,再快捷键生成定义函数代码# alt + 回车self.__display_students()elif item == "3":self.__delete_student()elif item == "4":self.__set_student()elif item == "5":self.__order_by_score()def __input_student(self):stu = StudentModel()stu.name = input("请输入学生姓名:")stu.age = int(input("请输入学生年龄:"))stu.score = int(input("请输入学生成绩:"))self.__controller.add_student(stu)def main(self):while True:self.__display_menu()self.__select_menu()def __display_students(self):for item in self.__controller.list_student:# print(f"{item.name}的编号是{item.sid},年龄是{item.age},成绩是{item.score}")print(item)def __delete_student(self):sid = int(input("请输入需要删除的学生编号:"))if self.__controller.remove_student(sid):print("删除成功")else:print("删除失败")def __set_student(self):stu = StudentModel()stu.sid = input("请输入学生编号:")stu.name = input("请输入学生姓名:")stu.age = int(input("请输入学生年龄:"))stu.score = int(input("请输入学生成绩:"))if self.__controller.update_student(stu):print("修改成功")else:print("修改失败")def __order_by_score(self):self.__controller.ascending_order()self.__display_students()class StudentController:"""学生控制器:处理核心功能,存储..."""__start_id = 100 # 大家的:系统不同界面使用的学生编号是一份(连续增加)@classmethoddef __set_student_id(cls, stu):cls.__start_id += 1stu.sid = cls.__start_iddef __init__(self):self.__list_student = [] # 自己的:系统不同界面使用自己数据(可以显示不同数据)@property # 只读属性:View类只能读取,不能修改def list_student(self):return self.__list_studentdef add_student(self, new_stu):# 设置学生编号StudentController.__set_student_id(new_stu)# 追加到列表中self.__list_student.append(new_stu)def remove_student(self, sid):"""在列表中删除学生信息:param sid: 学生编号:return: 是否成功"""stu = StudentModel(sid=sid)if stu in self.__list_student:# 重写Model类的eq方法self.__list_student.remove(stu)return Truereturn Falsedef update_student(self, stu):""":param stu::return:"""for i in range(len(self.__list_student)):if self.__list_student[i].sid == stu.sid:# self.list_student[i].name = stu.name# self.list_student[i].age = stu.age# self.list_student[i].score = stu.scoreself.__list_student[i].__dict__ = stu.__dict__return Truereturn Falsedef ascending_order(self):self.__list_student.sort()# 入口
view = StudentView()
view.main()
"""练习:重构商品信息管理系统中--在View直接打印商品 __str__--在Controller通过remove移除商品 __eq__--在Controller通过sort排序__gt__
"""class CommodityModel:"""商品模型:包装具体商品信息"""def __init__(self, name="", price=0, cid=0):self.name = nameself.price = priceself.cid = ciddef __str__(self):return "%s的编号是%s,单价是%s" % (self.name, self.cid, self.price)def __eq__(self, other):return self.cid == other.ciddef __gt__(self, other):return self.price > other.priceclass CommodityView:"""商品视图:处理商品界面逻辑,例如:输入输出商品信息"""def __init__(self):self.__controller = CommodityController()def __display_menu(self):print("按1键录入商品信息")print("按2键显示商品信息")print("按3键删除商品信息")print("按4键修改商品信息")print("按5键根据单价对商品信息排序")def __select_menu(self):item = input("请输入选项:")if item == "1":self.__input_commodity()elif item == "2":self.__display_commoditys()elif item == "3":self.__delete_commodity()elif item == "4":self.__set_commodity()elif item == "5":self.__order_by_price()def __input_commodity(self):cmd = CommodityModel()cmd.name = input("请输入商品名称:")cmd.price = int(input("请输入商品单价:"))self.__controller.add_commodity(cmd)def main(self):while True:self.__display_menu()self.__select_menu()def __display_commoditys(self):for item in self.__controller.list_commodity:# print("%s的编号是%s,单价是%s" % (item.name, item.cid, item.price))print(item) # 内部自动调用商品__str__def __delete_commodity(self):cid = int(input("请输入需要删除的编号:"))if self.__controller.remove_commodity(cid):print("删除成功")else:print("删除失败")def __set_commodity(self):cmd = CommodityModel()cmd.cid = int(input("请输入商品编号:"))cmd.name = input("请输入商品名称:")cmd.price = int(input("请输入商品单价:"))if self.__controller.update_commodity(cmd):print("修改成功")else:print("修改失败")def __order_by_price(self):self.__controller.ascending_order()self.__display_commoditys()class CommodityController:"""商品控制器:处理商品业务逻辑,例如:存储信息"""__start_id = 100 # 共享,只有一份@classmethoddef __set_commodity_id(cls, cmd):cmd.cid = cls.__start_idcls.__start_id += 1def __init__(self):self.list_commodity = [] # 独享,每个对象都有def add_commodity(self, new_cmd):CommodityController.__set_commodity_id(new_cmd)self.list_commodity.append(new_cmd)def remove_commodity(self, cid):""":param cid::return:"""cmd = CommodityModel(cid = cid)if cmd in self.list_commodity:self.list_commodity.remove(cmd)# 内部自动调用商品的__eq__return Truereturn Falsedef update_commodity(self, cmd):""""""for i in range(len(self.list_commodity)):if self.list_commodity[i].cid == cmd.cid:self.list_commodity[i].__dict__ = cmd.__dict__return Truereturn Falsedef ascending_order(self):self.list_commodity.sort() # 内部自动调用商品的__gt__view = CommodityView()
view.main()
练习
"""增加新功能:飞机
"""
# 缺点:违反了面向对象设计原则--开闭原则
# 允许增加新功能,但是不能修改客户端代码.
"""
class Person:def __init__(self, name=""):self.name = namedef go_to(self, position, vehicle):print("去" + position)if type(vehicle) == Car:vehicle.run()elif type(vehicle) == Airplane:vehicle.fly()class Car:def run(self):print("汽车在行驶")class Airplane:def fly(self):print("飞机在飞行")# 在使用时创建
zl = Person("老张")
car = Car()
air = Airplane()
zl.go_to("东北", car)
zl.go_to("东北", air)
"""# ------------------架构师--------------------
# 客户端代码
class Person:def __init__(self, name=""):self.name = namedef go_to(self, position, vehicle):print("去" + position)# 编码时,调用父类交通工具# 运行时,执行子类汽车/飞机vehicle.transport()# 父类(规范)
class Vehicle:def transport(self): #跟上面的transport名字保持一致pass# ------------------程序员--------------------
# 子类(功能实现)
class Car(Vehicle): #继承def transport(self): #重写print("汽车在行驶")class Airplane(Vehicle):# 重写快捷键 ctrl + odef transport(self):print("飞机在飞行")# 在使用时创建
zl = Person("老张")
car = Car()
air = Airplane()
zl.go_to("东北", car)
zl.go_to("东北", air)
i].dict = cmd.dict
return True
return False
def ascending_order(self):self.list_commodity.sort() # 内部自动调用商品的__gt__
view = CommodityView()
view.main()
练习```python
"""增加新功能:飞机
"""
# 缺点:违反了面向对象设计原则--开闭原则
# 允许增加新功能,但是不能修改客户端代码.
"""
class Person:def __init__(self, name=""):self.name = namedef go_to(self, position, vehicle):print("去" + position)if type(vehicle) == Car:vehicle.run()elif type(vehicle) == Airplane:vehicle.fly()class Car:def run(self):print("汽车在行驶")class Airplane:def fly(self):print("飞机在飞行")# 在使用时创建
zl = Person("老张")
car = Car()
air = Airplane()
zl.go_to("东北", car)
zl.go_to("东北", air)
"""# ------------------架构师--------------------
# 客户端代码
class Person:def __init__(self, name=""):self.name = namedef go_to(self, position, vehicle):print("去" + position)# 编码时,调用父类交通工具# 运行时,执行子类汽车/飞机vehicle.transport()# 父类(规范)
class Vehicle:def transport(self): #跟上面的transport名字保持一致pass# ------------------程序员--------------------
# 子类(功能实现)
class Car(Vehicle): #继承def transport(self): #重写print("汽车在行驶")class Airplane(Vehicle):# 重写快捷键 ctrl + odef transport(self):print("飞机在飞行")# 在使用时创建
zl = Person("老张")
car = Car()
air = Airplane()
zl.go_to("东北", car)
zl.go_to("东北", air)
相关文章:
pt05Encapsulationinherit
Encapsulation &inherit 封装继承 封装 向类外提供必要的功能,隐藏实现的细节, 代码可读性更高优势:简化编程,使用者不必了解具体的实现细节,只需要调用对外提供的功能。私有成员:作用:无需向类外提供…...

面向对象编程(基础)9:封装性(encapsulation)
目录 9.1 为什么需要封装? 而“高内聚,低耦合”的体现之一: 9.2 何为封装性? 9.3 Java如何实现数据封装 9.4 封装性的体现 9.4.1 成员变量/属性私有化 实现步骤: 成员变量封装的好处: 9.4.2 私有化…...
fate-serving-server增加取数逻辑并源码编译
1.什么是fate-serving-server? FATE-Serving 是一个高性能、工业化的联邦学习模型服务系统,专为生产环境而设计,主要用于在线推理。 2.fate-serving-server源码编译 下载fate-serving-serving项目(GitHub - FederatedAI/FATE-Serving: A scalable, h…...

循环队列、双端队列 C和C++
队列 目录 概念 实现方式 顺序队列 循环队列 队列的数组实现 用循环链表实现队列 STL 之 queue 实现队列 STL 之 dequeue 实现双端队列 概念 队列是一种特殊的线性表,它只允许在表的前端(称为队头,front)进行删除操作…...
正则表达式(语法+例子)
文章目录一、介绍二、语法1、匹配字符2、表示数量的字符3、边界字符4、其他字符5、转义字符三、例子1、邮箱2、用逗号分隔的数字集合1,23、允许一位小数4、20yy-mm-dd日期格式5、手机号6、匹配html、xml标签一、介绍 正则表达式(Regular Expression)&am…...

Properties和IO流集合的方法
方法名说明void load(InputStream inStream)从输入字节流读取属性列表(键和元素)void load(Reader reader)从输入字符流读取属性列表(键和元素对)void store(OutputStream out,String comments)将此属性列表(键和元素对…...

python 生成器、迭代器、动态新增属性及方法
目录 一、生成器 1、生成器定义 2、生成器存在的意义 3、创建生成器方式一(生成器表达式) 4. 创建生成器方式二(生成器函数) 1. 生成器函数 2. 生成器函数的工作原理 5. 总结 1. 什么是生成器 2. 生成器特点 二、迭代器…...
Java处理JSON
Java处理json有很多种方法,在这里总结一下。 1 Jackson Spring MVC 默认采用Jackson解析Json,出于最小依赖的考虑,也许Json解析第一选择就应该是Jackson。 1.1 引入的包 Jackson核心模块由三部分组成:jackson-core、jackson-a…...
58-Map和Set练习-LeetCode692前k个高频单词
题目 给定一个单词列表 words 和一个整数 k ,返回前 k 个出现次数最多的单词。 返回的答案应该按单词出现频率由高到低排序。如果不同的单词有相同出现频率, 按字典顺序 排序。 示例 1: 输入: words ["i", "love", …...

线程生命周期及五种状态
文章目录一、线程生命周期及五种状态1、New(初始化状态)2、Runnable(就绪状态)3、Running(运行状态)4、Blocked(阻塞状态)5、Terminated(终止状态)二、线程基本方法1、线程等待(wait)2、线程睡眠(sleep)3、…...
OBCP第八章 OB运维、监控与异常处理-灾难恢复
灾难恢复是指当数据库中的数据在被有意或无意破坏后复原数据库所需要执行的活动 回收站:回收站在原理上说就是一个数据字典表,放置用户删除的数据库对象信息。用户删除的东西被放入回收站后,其实仍然占据着物理空间,除非您手动进…...

亚马逊云科技Serverless Data:数字经济下的创新动能
Serverless时代已经到来!企业的技术架构,总是伴随着不断增长的数据与日趋复杂的业务持续演进。如何通过构建更易用的技术架构来聚焦在业务本身,而不必在底层基础设施的管理上投入过多的精力,是数据驱动型企业需要思考的重要议题。…...
【Ruby学习笔记】15.Ruby 异常
Ruby 异常 异常和执行总是被联系在一起。如果您打开一个不存在的文件,且没有恰当地处理这种情况,那么您的程序则被认为是低质量的。 如果异常发生,则程序停止。异常用于处理各种类型的错误,这些错误可能在程序执行期间发生&…...

聊聊MySQL主从延迟
文章目录 MySQL 的高可用是如何实现的呢?二、什么是主备延迟?三、主备延迟常见原因1、备库机器配置差2、备库干私活3、大事务四、主库不可用,主备切换有哪些策略?1、可靠优先2、可用优先实验一实验二3、结论MySQL 的高可用是如何实现的呢? 高可用性(high availability,缩…...
【C++从0到1】19、C++中多条件的if语句
C从0到1全系列教程 1、多条件的if语句 语法: if (表达式一) { // 表达式一为真时执行的语句。 } else if (表达式二) {// 表达式二为真时执行的语句。 } else if (表达式三) {// 表达式三为真时执行的语句。 } …… else if (表达式n) {// 表达式n为真时执行的语句。…...

【多微电网】计及碳排放的基于交替方向乘子法(ADMM)的多微网电能交互分布式运行策略研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

Linux(centos7)安装防火墙firewalld及开放端口相关命令
安装firewalld 防火墙命令: yum install firewalld 安装完成,查看防火墙状态为 not running,即未运行,输入命令开启: 添加开放端口: 防火墙相关命令: 查看防火墙状态 systemctl status firewa…...

Linux部署.Net Core Web项目
本文主要记录我在Linux(Ubuntu)上部署.net core 的操作记录,也便于以后部署。 如对您有所帮助,不胜荣幸~ 文章目录前言一、准备工作1. 版本信息2. windows端web项目二、操作步骤1. Linux 配置 .net 运行环境1.1 查看最新 .net 运行环境的下载路径1.2 安装…...

【C++】STL之stack、queue的使用和模拟实现+优先级队列(附仿函数)+容器适配器详解
之前的一段时间,我们共同学习了STL中一些容器,如string、vector和list等等。本章我们将步入新阶段的学习——容器适配器。本章将详解stack、queue的使用和模拟实现优先级队列(附仿函数)容器适配器等。 目录 (一&…...

第⑦讲:Ceph集群RGW对象存储核心概念及部署使用
文章目录1.RadosGW对象存储核心概念1.1.什么是RadosGW对象存储1.2.RGW对象存储架构1.3.RGW对象存储的特点1.4.对象存储中Bucket的特性1.4.不同接口类型的对象存储访问对比2.在集群中部署RadosGW对象存储组件2.1.部署RGW组件2.2.集群中部署完RGW组件后观察集群的信息状态2.3.修改…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...

html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...

技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...