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.修改…...

从异步到promise
一,背景 1.1,js的单线程 这一切,要从js诞生之初说起,因为js是单线程的语言。 js单线程原因:作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程&…...

Linux系统中进行JDK环境的部署
一、为什么需要部署JDK。 JDK:Java Development Kit,是用于Java语言开发的环境。 部署JDK不需要懂得Java语言,只需要掌握Linux相关命令即可。 二、部署版本与环境。 系统:安装在VMware环境下的CentOS7.6; JDK版本&a…...

Leetcode.1033 移动石子直到连续
题目链接 Leetcode.1033 移动石子直到连续 Rating : 1421 题目描述 三枚石子放置在数轴上,位置分别为 a,b,c。 每一回合,你可以从两端之一拿起一枚石子(位置最大或最小),并将其放入…...

【Java】在SpringBoot中使用事务注解(@Transactional)时需要注意的点
在SpringBoot中使用事务注解(Transactional)时需要注意的点Transactional是什么使用事务注解(Transactional)时需要注意的点Transactional是什么 Transactional是Spring框架提供的一个注解,用于声明事务边界和配置事务…...

找到序列最高位的1和最高位的0并输出位置
前言: 该题为睿思芯科笔试题,笔试时长20分钟。 题目描述 接口如下: module first_1_and_0#(parameter WIDTH 8 )(input [WIDTH-1:0] data_in ,input target ,output exist ,outpu…...

面试总结sdiugiho
一、进程与线程的区别 进程: 一个在内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程可以有多个线程; windows 任务管理器中 一个 exe 就是一个进程。 线程: 进程中的一个执行任务(控制…...

WIN10無法再使用 IE 瀏覽器打开网页解决办法
修改 Registry(只適用 Win10) 微軟已於 2023 年 2 月 14 日永久停用 Internet Explorer,會透過 Edge 的更新讓使用者開啟 IE 時自動導向 Edge,其餘如工作列上的圖示,使用的方法則是透過「品質更新」的 B 更新來達成&am…...

搭建SpringBoot和Mysql Demo
1. 引言 在上一篇文章中,介绍了如何搭建一个SpringBoot项目;本篇文章,在上一篇文章的基础上,接着介绍下怎样实现SpringBoot和MySQL的整合。在后端开发中,数据库开发是绕不开的话题,开发中很多的时间都是在…...

晶振03——晶振烧坏的原因
晶振03——晶振烧坏的原因 首先要清楚的一件事情是:晶振分为无源晶振与有源晶振两大类。基于这两类晶振的内部结构与工作原理的差异,晶振被烧坏的情况也要分为两大类: 针对无源晶振被烧坏的情况有以下两点: 1、手焊操作不当 假…...

项目管理的难点
一、项目团队建设 建设一支高效的项目团队,明确团队队员的职责是项目经理进行项目管理的首要条件,也是项目目标能否实现的关键。 1.1 学会放权 任何人都不能掌握所有的知识和技能,要敢于相信别人,让别人去做。 放权就要选择最…...