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)