类的定义
方式1
在之前的学习过程中,我们都使用了这种定义类的语法(旧式类):


方式2
在编写类时,也可以写成如下格式(旧式类):


方式3
此外,还有一种更为常见的定义类的语法(新式类),如下:
object是所有类的父类,Python中所有的类都直接或者间接继承自object类.


继承
什么是继承


- 继承: 一个类从另一个已有的类获得其成员的相关特性,就叫作继承!(站在子类角度)
- 派生: 从一个已有的类产生一个新的类,称为派生! (站在父类角度)
- 很显然,继承和派生其实就是从不同的方向来描述的相同的概念而己,本质上是一样的!
- 父类: 也叫作基类,就是指已有被继承的类!
- 子类: 也叫作派生类或扩展类
单继承
单继承就是一个子类只能继承自一个父类,不能继承多个类。这个子类会有具有父类的属性和方法。

多继承
多继承就是一个类同时继承了多个父类,并且同时具有所有父类的属性和方法。
- 例如: 孩子会继承父亲和母亲的方法和属性

- 继承的优先级: 从左往右,就近原则.
- MRO(Method Resolution Order): 方法解析顺序
- 当一个类有多个父类时,默认使用第一个父类的同名属性和方法,
- 可以使用 类名.mro 属性 或 类名.mro() 方法查看调用的先后顺序。

方法重写和属性重写
重写也叫作覆盖,就是当子类属性或方法与父类的属性或方法名字相同时,从父类继承下来的成员可以重新定义! 子类重写父类的属性和方法,优先会调用子类的属性和方法
调用层次: 遵循就近原则,子类有就用,没有就去父类找,依次查找其所有的父类,有就用,没有就报错.


子类调用父类方法
子类中仍想要保留父类的行为,则需要在子类中调用父类方法. 可以直接使用父类名来进行调用
语法: 父类名.父类函数名(self)
特点: 精准访问, 想找哪个父类, 就调用哪个父类

使用super()调用父类方法
语法: super().父类函数名(self)
注意: 使用super()可以自动查找父类,有就用, 没有就报错 (从左往右逐层查找)
建议: 适合单继承使用,多继承不建议使用

多层继承
object <- Master,School <- Prentice <- Tusun

封装
什么是封装?
在软件编程中,将属性和方法书写到类的里面的操作即为封装,封装可以为属性和方法添加私有权限。

私有属性和私有方法
在Python中,可以为属性和方法设置私有权限,即设置某个属性或方法不继承给子类。
设置私有属性和方法的方式:在属性或方法名前面加上 __ (双下划线),格式:

私有属性和方法使用规则:
- 只能在类的内部使用,不能在类的外部使用;
- 如果想在类的外部使用通过公共接口
定义和获取私有属性

私有属性不能直接访问,在Python中,一般定义方法名'get_xx'用来获取私有属性,定义'set_xx'用来修改私有属性值。
定义和获取私有方法

访问私有方法,可以使用重新设置一个公有方法来访问。
多态
多态,指的是多种状态。比如: 同样一个函数在不同的场景下有不同的状态
同样的行为(函数),传入不同的对象,得到不同的状态


多态成立的条件
实现多态的三个条件:
1、有继承 (定义父类、定义子类,子类继承父类)
2、函数重写(子类重写父类的函数)
3、父类引用指向子类对象 (子类对象传给父类对象调用者)
"""
演示多态
"""
# 1.有继承
class Animal: # 抽象类: 定义了抽象方法的类
def speak(self): # 抽象方法: 没有方法体的方法
pass
# 2.有函数重写
class Dog(Animal):
def speak(self):
print("狗叫: 汪汪汪")
class Cat(Animal):
def speak(self):
print("猫叫: 喵喵喵")
# 3.父类引用指向子类对象 (多态函数)
def make_noise(an: Animal): # 限制an类型
# an:Animal = Dog()
an.speak()
if __name__ == '__main__':
d = Dog()
make_noise(d) # 狗叫: 汪汪汪
c = Cat()
make_noise(c) # 猫叫: 喵喵喵
多态案例
构建对象对战平台object_play
- 英雄一代战机(战斗力60)与敌军战机(战斗力70)对抗。英雄1代战机失败!
- 卧薪尝胆,英雄二代战机(战斗力80)出场!,战胜敌军战机!
- 对象对战平台object_play,代码不发生变化的情况下,完成多次战斗
思路分析:
- 抽象战机类 HeroFighter AdvHeroFighter; 敌机 EnemyFighter;
- 构建对象战斗平台,使用多态实现
代码实现:
# 1.定义英雄机1代
class HeroFighter(object):
def power(self):
return 60
# 2.定义英雄机2代
class AdvHeroFighter(HeroFighter):
def power(self):
return 80
# 3.定义敌机1代
class EnemyFighter(object):
def power(self):
return 70
# 4.构建对战函数 (多态方法)
def object_play(hero, enemy):
# 参1: 英雄机, 参数2: 敌机
# 看面向对象代码,要时刻注意什么时候发生多态
if hero.power() > enemy.power():
print("英雄机战胜敌机!")
else:
print("敌机战胜英雄机!")
if __name__ == '__main__':
h1 = HeroFighter()
h2 = AdvHeroFighter()
e1 = EnemyFighter()
# 一代战机出战
object_play(h1, e1)
# 二代战机出战
object_play(h2, e1)
多态的好处:
1、通过多态语法轻松的实现模块和模块之间的解耦合; 实现了软件系统的可扩展;
2、对解耦合解释:
- 搭建的平台函数相当于任务的调用者;
- 子类、孙子类重写父类的函数,相当于子任务;
- 相当于任务的调用者和任务的编写者进行了解耦合;
3、对可扩展的解释:
- 同一个多态方法, 传入不同的对象, 就会有不同的结果
为了更好的使用多态这个特性,行业专家们又提出来抽象类,抽象接口的概念

- 抽象类就好比定义一个标准,包含了一些抽象的方法,要求子类必须实现。


- 抽象类的概念(也可以称之为接口)
- 抽象类: 含有抽象方法的类称之为抽象类
- 抽象方法: 方法体是空实现的(pass)称之为抽象方法
- 这种设计的含义是:
- ·父类用来确定有哪些方法 (父类制定接口标准)·
- 具体的方法实现有子类来实现 (子类实现接口标准)
其他特性
对象属性


类属性


类方法


静态方法


如果函数中要用 类对象,就定义成类方法,否则定义成静态方法,除此外,并无任何区别.
案例
需求分析
- 基本需求
- a.可以显示基本的版本信息和操作界面;
- b.可以通过键盘输入信息来完成基本功能,例如选择序号、确认退出、添加学生、修改信息等
- c.学生属性信息有姓名、性别、年龄、联系方式、描述信息等;
- d.使用系统可对学生信息进行添加、修改、删除、查询等操作;
- e.可以使用文件对学生信息进行加载、保存等;
- f.可重复对学生进行增删查改操作,当确认退出系统后,则直接退出系统;
- g.请使用面向对象的编程思想完成项目。

- 角色分析
- 学生管理系统类 和 学员类
- 一般一个角色一个程序文件
- 项目主程序入口为main.py
开发实现
-
设计学生类
"""
学生类
"""
class Student:
def init(self, name, gender, age, phone, desc):
"""
初始化属性信息
:param name: 学生姓名
:param gender: 性别
:param age: 年龄
:param phone: 手机号
:param desc: 描述
"""
self.name = name
self.gender = gender
self.age = age
self.phone = phone
self.desc = descdef __str__(self): return f'姓名: {self.name} 年龄: {self.age} 性别: {self.gender} 手机号: {self.phone} 描述: {self.desc}'if name == 'main':
s1 = Student("张三", "男", 18, "12345678901", "描述")
print(s1) -
设计系统框架
"""
系统管理类
"""
class Cms(object):
def init(self):
self.stu_list = []def show_emnu(self): print("*" * 23) print("学生管理系统") print("\t1.添加学生信息") print("\t2.删除学生信息") print("\t3.修改学生信息") print("\t4.查询某个学员") print("\t5.查询全部学员") print("\t6.保存信息") print("\t0.退出系统") print("*" * 23) def add_stu(self): pass def del_stu(self): pass def update_stu(self): pass def query_stu(self): pass def query_all_stu(self): pass def save_stu(self): pass def start(self): while True: self.show_emnu() input_num = input("请输入操作编号:") if input_num == "1": print("添加学生信息") self.add_stu() elif input_num == "2": print("删除学生信息") self.del_stu() elif input_num == "3": print("修改学生信息") self.update_stu() elif input_num == "4": print("查询学生信息") self.query_stu() elif input_num == "5": print("查询全部学生信息") self.query_all_stu() elif input_num == "6": print("保存学生信息") self.save_stu() elif input_num == "0": result = input("确认要退出吗? (Y?N)") if result.lower() == "y": print("感谢使用, 期待下次再会!") break else: print("输入错误,请重新输入:")if name == 'main':
cms = Cms()
cms.start() -
完成入口文件
"""
入口文件
"""
from cms import Cmsif name == 'main':
cms = Cms()
cms.start()

-
实现学生的增删改查
"""
系统管理类
"""
from student import Studentclass Cms(object):
def init(self):
self.stu_list = [
Student("张三", "男", 18, "12345678901", "描述"),
Student("李四", "女", 19, "12345678902", "描述"),
Student("王五", "男", 20, "12345678903", "描述"),
Student("赵六", "女", 21, "12345678904", "描述"),
Student("孙七", "男", 22, "12345678905", "描述"),
]def show_emnu(self): print("*" * 23) print("学生管理系统") print("\t1.添加学生信息") print("\t2.删除学生信息") print("\t3.修改学生信息") print("\t4.查询某个学员") print("\t5.查询全部学员") print("\t6.保存信息") print("\t0.退出系统") print("*" * 23) def add_stu(self): name = input("输入学生姓名:") gender = input("输入学生性别:") age = int(input("输入学生年龄:")) phone = input("输入学生电话:") desc = input("输入学生描述信息:") stu = Student(name, gender, age, phone, desc) self.stu_list.append(stu) print(f"添加学生 {name} 成功") def del_stu(self): name = input("输入要删除学生的姓名:") for stu in self.stu_list: if stu.name == name: self.stu_list.remove(stu) print(f"删除学生 {name} 成功") break else: print(f"没有找到学生 {name}") def update_stu(self): name = input("输入要修改学生的姓名:") for stu in self.stu_list: if stu.name == name: stu.name = input("输入学生姓名:") stu.gender = input("输入学生性别:") stu.age = int(input("输入学生年龄:")) stu.phone = input("输入学生电话:") stu.desc = input("输入学生描述信息:") print(f"修改学生 {name} 成功") break else: print(f"没有找到学生 {name}") def query_stu(self): name = input("输入要查询学生的姓名:") for stu in self.stu_list: if stu.name == name: print(stu) break else: print(f"没有找到学生 {name}") def query_all_stu(self): if len(self.stu_list) == 0: print("暂无学生信息!") return else: for stu in self.stu_list: print(stu) print("") def save_stu(self): pass def start(self): while True: self.show_emnu() input_num = input("请输入操作编号:") if input_num == "1": self.add_stu() elif input_num == "2": self.del_stu() elif input_num == "3": self.update_stu() elif input_num == "4": self.query_stu() elif input_num == "5": self.query_all_stu() elif input_num == "6": self.save_stu() elif input_num == "0": result = input("确认要退出吗? (Y?N)") if result.lower() == "y": print("感谢使用, 期待下次再会!") break else: print("输入错误,请重新输入:")if name == 'main':
cms = Cms()
cms.start() -
保存学生信息到文件
- 扩展 dict 方法

-
完整的功能实现
"""
系统管理类
"""
import timefrom student import Student
class Cms(object):
def init(self):
self.stu_list = []@staticmethod def show_emnu(): print("*" * 23) print("学生管理系统") print("\t1.添加学生信息") print("\t2.删除学生信息") print("\t3.修改学生信息") print("\t4.查询某个学员") print("\t5.查询全部学员") print("\t6.保存信息") print("\t0.退出系统") print("*" * 23) def add_stu(self): name = input("输入学生姓名:") gender = input("输入学生性别:") age = int(input("输入学生年龄:")) phone = input("输入学生电话:") desc = input("输入学生描述信息:") stu = Student(name, gender, age, phone, desc) self.stu_list.append(stu) print(f"添加学生 {name} 成功") def del_stu(self): name = input("输入要删除学生的姓名:") for stu in self.stu_list: if stu.name == name: self.stu_list.remove(stu) print(f"删除学生 {name} 成功") break else: print(f"没有找到学生 {name}") def update_stu(self): name = input("输入要修改学生的姓名:") for stu in self.stu_list: if stu.name == name: stu.name = input("输入学生姓名:") stu.gender = input("输入学生性别:") stu.age = int(input("输入学生年龄:")) stu.phone = input("输入学生电话:") stu.desc = input("输入学生描述信息:") print(f"修改学生 {name} 成功") break else: print(f"没有找到学生 {name}") def query_stu(self): name = input("输入要查询学生的姓名:") for stu in self.stu_list: if stu.name == name: print(stu) break else: print(f"没有找到学生 {name}") def query_all_stu(self): if len(self.stu_list) == 0: print("暂无学生信息!") return else: for stu in self.stu_list: print(stu) print("") def save_stu(self): with open("/stu_data.txt", "w", encoding="utf-8") as dest_f: # 把[学生对象, ...] 转成 [学生对象字典, ...] stu_dict = [stu.__dict__ for stu in self.stu_list] # 把字典列表持久化 dest_f.write(str(stu_dict)) def out(self): result = input("确认要退出吗? (Y?N)") if result.lower() == "y": self.save_stu() print("感谢使用, 期待下次再会!") return True else: return False def load_stu(self): try: with open("/stu_data.txt", "r", encoding="utf-8") as src_f: stu_data = src_f.read() # 把字符串转换成字典列表 stu_list = eval(stu_data) # 如果列表是空重新赋值 if len(stu_list) == 0: stu_list = [] # 把字典列表转换成学生对象列表 self.stu_list = [Student(**stu) for stu in stu_list] except: with open("/stu_data.txt", "w", encoding="utf-8") as dest_f: pass def start(self): self.load_stu() while True: time.sleep(1) self.show_emnu() input_num = input("请输入操作编号:") if input_num == "1": self.add_stu() elif input_num == "2": self.del_stu() elif input_num == "3": self.update_stu() elif input_num == "4": self.query_stu() elif input_num == "5": self.query_all_stu() elif input_num == "6": self.save_stu() print("学生信息保存成功!") elif input_num == "0": res = self.out() if res: break else: print("输入错误,请重新输入:")if name == 'main':
cms = Cms()
cms.start()