二、面向对象
1. 面向对象编程思想
所谓的编程思想,就是人们利用计算机来解决实际问题的一种思维方式,常见的编程思想有面向过程和面向对象,很多计算机语言的语法各不相同,但是它们基本的编程思想却是差不多的,而Python是同时支持面向对象和面向过程的编程语言!
1.1 面向过程
传统的面向过程的编程思想总结起来就八个字——>自顶向下,逐步细化!
将要实现的功能描述为一个从开始到结束按部就班的连续的“步骤”
依次逐步完成这些步骤,如果某一个步骤的难度较大,又可以将该步骤再次细化为若干个子步骤,以此类推,一直到结尾并得到我们想要的结果
程序的主体是函数,一个函数就是一个封装起来的模块,可以实现特定的功能,程序的各个子步骤也往往就是通过相关的函数来完成的!从而实现代码的重用与模块化编程
核心为:函数
举个栗子:大家以来报名学习这件事情,可以分成哪些步骤?开始 → 学员提出报名,提供相关材料 → 学生缴纳学费,获得缴费凭证 一 教师凭借学生缴费凭证进行分配班级- 班级增加学生信息 → 结束所谓的面向过程,就是将上面分析好了的步骤,依次执行就行了!
1.2 面向对象
2. 类定义
2.1 类的定义
Python3中类分为:经典类 和新式类
经典类:不由任意内置类型派生出的类,称之为经典类
class 类名:
代码
新式类:
class 类名():
代码
这就是一个类,只不过里面什么都没有!其中,类名既可以大写也可以小写,遵守一般的标识符的命名规则(以字母、数字和下划线构成,并且不能以数字开头),一般为了和方法名相区分,类名的首字母一般大写!(大驼峰法)
案例:
'''
类是相同或相似属性和方法的一组对象的集合,
是一个抽象概念如果想获得一个对象,首先应该创建一个类,基本语法:class 类名(object):
#属性=> 变量
#方法=> 函数
注意事项:类名在Python中,一般采用大驼峰的命名法,其主要由字母、数字以及下划线,但是不能以数字开头!!!注意事项:类在定义构成中,只是描述了一下未来这个对象所拥有的属性和方法,但是其本身并没有并调用,只有在实例化对象时其才真正执行!
'''
class Person(object):
# 属性
# 方法
def eat(self):
print('吃')
def run(self):
print('跑')
2.2 类的实例化
类是具有相同或相似属性或方法的一组对象的集合,其是一个抽象概念。要想把其创建为具体的对象,需要经过实例化的过程。
获取对象 => 类的实例化
类是一个抽象概念,可以同时产生多个对象。
对象名称 = 类名()产生对象以后,则这个对象会自动拥有类中的所有公共属性和公共力法,
通过:
对象名称.属性 或者 对象名称.方法()
方式实现对白身属性和方法的调用
类的实例化 =>产生一个甚至多个对象
class Person(object):
# 属性
# 方法
def eat(self):
print('吃')
def run(self):
print('跑')
p = Person()
p.eat() #吃
类是一个抽象概念,在定义时,其并不会真正的占用计算机的内存空间。但是对象是一个具体的事务,所以其要占用计算机的内存空间。
3. 类属性
3.1 类中self关键字
有一个问题:在我们定义类的时候,我们描述的是未来实例化对象所拥有的属性和方法,但是为什么所有的对象方法都要有一个多数self,self关键字到底代表什么含义呢?
在类中定义的对象方法中的self参数,与实例化产生的对象内存地址一致,所以代表两者指向了相同的内存空间。所以self关键字就代表实例化对象本身。
简单来说:准实例化了Person类,类中的对象方法就指向!
由于self关键字在类的内部就代表对象本身,所以我们在方法的里面可以使用self调用自身的属性或方法。
class Person(object):
# 属性
# 方法
def eat(self):
print('吃')
def run(self):
print('跑')
def speak(self):
print(self)
p = Person()
print(p) # 0x0000029ED361AFD0
p.speak() # 0x0000029ED361AFD0
3.2 添加和获取类属性
基本语法:
对象名.属名 = 值
快速入门:
p1.name='老土”
p1.age=18
p1.address='北京
在Python中,每个对象,般都是由两部分内容组成的:①属性 ②方法
我们既可以在类的内部也可以在类的外部为其对象添加属性或获得属性
在类的外部如何添加属性
对象名称.属性 =属性信,如果属性值是 个字符串类型,达需要使用引号引起来!
示例:
class Person(object):
# 属性
# 方法
def eat(self):
print('吃')
def run(self):
print('跑')
# 实例化产生对象
p1 = Person()
# 在类的外部添加属性
p1.name = '小明'
p1.age = 12
# 在类的外部获得p1的属性
print(p1.name) # 小明
print(p1.age) # 12
在类的外部为对象动态属性,添加完成后,我们是否可以在类的内部对其进行获取呢?
在类的内部,我们可以通过刘象方法中的self关键字来文现刘自身属性和方法的调用
①self指向谁?谁实例化这个类,self就指问谁(对象) (self => p1)
②self有何作用?可以通过self.属性或者self.方法()形式来实现对自身属性或方法的调用
class Person(object):
# 属性
# 方法
def eat(self):
print('吃')
def print_info(self):
print(f'姓名{self.name}')
print(f'姓名{self.age}')
# 实例化产生对象
p1 = Person()
# 在类的外部添加属性
p1.name = '小明'
p1.age = 12
# 通过p1对象,调用自身的print_info 方法
p1.print_info() # 姓名小明,姓名12
在类的内部如何添加属性
类的内部直接描述未来对象所拥有的些公共性,需要使用魔术方法来文现!
3.3 类属性
对象属件(成员属性)是由这个类产生的对象所拥有的属。
类属性:并小是由实例化对象拥有的,而是这个类所拥有的属性,可以解为是所有对象共同拥有的属性,但是其小属丁某应用场景:比如我们想知道出这个类到底生成了多少个对象
class 类名称()
属性 = 属性名
类属性如何访问呢?既可以在类的里面也可以在类的外面
类名.类属性
对象.类属性(出可以、但是不荐)
Person 为类 Person.count
p1 为对象 p1.count
里面的方法为实例
class Person(object)
# 定义一个类属性:用于统计到底由这个类产生了多少个对象
count =0
# 通过_init_-魔术方法定义的都是对象属件
def _init_ (self,name, age):
self.name = name
self.age =age
# 对类属性进行累加斗数
Person.count += 1
p1 = Person('小明'23)p2 = Person('小美',18)
3.4 类方法
类方法:在Python代码中,类属性与对象属性一样,都强调封装特性,不建议直接在类的外部直接对类属性进行操作如果想在类的外部获取类属性的信息,必须使用类方法来实现。
类方法 =>基本语法
class 类名称():
类属性 = 属性值@classmethod =>装饰器
def 类方法(cls):
因为这个方法属于类方法,所以cls代表这个类本身调用类方法:
- 类名称.类方法() => 强烈推荐使用第一种
- 对象.类方法()
案例:统计TO0l工具类到底生成了多少个工具类对象
class Tool(object):
# 定义一个类属性
count = 0
# 定义对象属性
def __init__(self, name):
self.name = name
# 对类属性进行操作
Tool.count +=1
# 定义一个类方法 =>专门用于操作类属性
@classmethod
def getCount(cls):
return f'一共实例化了{Tool.count}个对象'
t = Tool('斧头')
print(Tool.getCount()) #一共实例化了1个对象
3.5 静态方法
在开发时,如果需要在类中封装一个方法,这个方法:
① 既 不需要访问实例属性或者调用实例方法
② 也 不需要访问类属性或者调用类方法这个时候,可以把这个方法封装成一个静态方法
基本语法
@staticmethod
def 静态方法名( ):
pass
案例:
class StudentManager(object):
# 打印系统功能菜单
@staticmethod
def menu():
print('-'* 40)
print('欢迎使用学生管理系统V1.0')
print('【1】添加学员信息')
print('【2】删除学员信息')
print('【3】修改学员信息')
print('【4】查询学员信息')
print('-'* 40)
# 调用静态方法 =>类名,静态方法()或者 对象.静态方法()
StudentManager.menu()
4. 魔术方法
4.1 __init__ 方法(初始化方法)
使用__init__()方法,其作用:
实例化对象时,连带其中的参数,会一并传给__init__函数自动并执行它。 __init__()函数的参数列表会在开头多出一项,它永远指代新建的那个实例对象,Python语法要求这个参数必须要有,名称为self。
实际工作场景:
①在类的定义:用于提述对象未来所拥有的公从属性
②)还可以用丁进行系统的初始化工作 =>比如文件操作中的打开文件,数据库操作中的连接数据库等等魔术方法:
① 在什么情况下,__init__()会被触发(调用),当实例化对象时,__init__()方法会自动被触发实例化多少次,__init__()方法就会被调用多少次②)在实际工作中,主要用于公共属性的初始化或者项日的初始化工作
# 1、定义一个类
class Person():
#初始化实例对象属性
def __init__(self, name, age):
# 赋予name属性、age属性给实例化对象本身
# self.实例化对象属性 = 参数
self.name =name
self.age = age
#2、实例化对象并传入初始化属性值
p1= Person('孙悟空',588)
# 3、调用p1对象自身属性name与age
print(p1 .name)
print(p1.age)
__init__()方法,在创建一个对象时默认被调用,不需要手动调用
__init__(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象2引用传递过去。
4.2 __str__ 方法
当使用print输出对象的时候,默认打印对象的内存地址。如果类定义了--str--方法,那么就会打印从在这个方法中 return 的数据。(另外要特别注意_str_方法返回 字符串类型 的数据)
- 当我们便用print()直接打印对象时,__str__()魔术方法会自动被触发
- 当我们需要打印输出某个对象的信息时,一般都可以定义__str__()魔术方法
# 1、定义一个类
class Car():
#首先定义一个__init__方法,用于初始化实例对象属性
def __init__(self, brand, model, color):
self.brand = brand
self.model = model
self.color = color
# 定义一个__str__内置魔术方法,用于输出小汽车的相关信息
def __str__(self):
return f'汽车品牌:{self.brand},汽车型号:{self.model},汽车颜色:{self.color}'
# 2、实例化对象c1'
c1 = Car('奔驰','S688','黑色')
print(c1)
输出: 汽车品牌:奔驰,汽车型号:S688,汽车颜色:黑色
__str__这个魔术方法是在类的外部,使用print(对象)时,自动被调用的
在类的内部定义__str__方法时,必须使用return返回一个字符串类型的数据
4.3 __del__方法
init_方法与__del方法时一对
当删除对象时(调用del删除对象或文件执行结束后),python解释器也会默认调用__de1__()方法
在Python屮,其被称之为删除方法(在其他编程语言中,也称之为析构方法)
- __init__():构造方法,项目初始化
- __del__():析构方法,项目清理或项目收尾
__del__()当对象被删除时会自动被发 =>
① 手动del 对象
② 当程序执行结束,内存开始清理对象时
在实际工化中,__del__()方法主要用十清除对象或者实现项月清理工作、如关闭文件,关闭数据库连接
class Person():
#构造函数__init__
def __init__(self, name, age):
self.name = name
self.age = age
#析构方法__del__
def __del__(self):
print(f'{self}对象已经被删除')
#实例化对象
p1 = Person('白骨精',188)
# 删除对象p1
del p1 #对象已经被删除
5. 综合案例
5.1 学生成绩打印
源码如下:
'''
案例1:定义学员信息类,包含姓名、成绿属性,定义成绩打印方法(9日分及以上显示优秀,80分及以上显示良好,70分及以上
显示中等,60分及以上显示台格,60分以下显示不及格)
记住:在实际工作中,为了保证数据的安全性, 般小建议在类外部直接调用白身属性,如果想调用白身属性都是通过对应的方法
实现的!
'''
class Student(object):
# 公共属性
def __init__(self,name,score):
self.name = name
self.score = score
# 公共方法
def print_grade(self):
if self.score>= 90:
print(f'{self.name}成绩为{self.score}分,优秀!')
elif 80 <= self.score < 90:
print(f'{self.name}成绩为{self.score}分,良好!')
elif 70 <= self.score < 80:
print(f'{self.name}成绩为{self.score}分,中等!')
elif 60 <= self.score < 70:
print(f'{self.name}成绩为{self.score}分,合格!')
else:
print(f'{self.name}成绩为{self.score}分,不合格!')
s1 = Student('tom',11)
s1.print_grade()
5.2 小明爱跑步
案例2:小明体重75.0公斤,小明每次跑步会减掉0.10公斤,小明每次吃东西体重增加0.20公斤分析:① 对象:小明② 属性:姓名、体重③ 方法:跑步、吃东西
源码如下:
'''
案例2:小明体重75.0公斤,小明每次跑步会减掉0.10公斤,小明每次吃东西体重增加0.20公斤
分析:① 对象:小明 ② 属性:姓名、体重 ③ 方法:跑步、吃东西
'''
class Person(object):
# 定义自身属性
def __init__(self, name, weight):
self.name = name
self.weight = weight
# 定义自身方法
def run(self):
# 跑步减少体重
self.weight -= 0.1
def eat(self):
# 吃东西增加体重
self.weight += 0.2
# 打印自身信息 定义一个魔术方法
def __str__(self):
return f'我是{self.name},体重{self.weight:.2f}KG'
p1 = Person('小明',70)
# 跑步
p1.run()
print(p1)
p1.eat()
print(p1)
5.3 搬家具
1.家具分不同的类型(Bed床 => 硬板床、席梦思),并占用不同的面积(自身特征 => 属性 =>5)
2.输出家具信息时,显示家具的类型(name)和家具占用的面积(area =>面积)
3.房子有自己的地址(addr)和占用的面积(area)4.房子可以添必家具 =>add_item()=>[],如果房子剩余面积可以容纳家具(房子剩余面积>=家具占地面积),则提示家具添加成功;否则提示添加失败
5.输出房子信息时(print 房子对象),可以显示房子的地址、占地面积、家具信息
经过分析:大概有两个对象 =>房子对象、家具对象 => 具体一点 => 柜子、桌子、椅子或者床等等
源码如下:
class House(object):
def __init__(self, addr, area):
self.addr = addr
self.area = area
# 由于要摆放家具,所以需要定义一个专门属性,用于存放家具信息
self.items = [] # 将来结构 =>[bed家具对象2,家具对象3]
# 向房子中添加家具
def addItem(self, item): # item代表用于接收的家具对象,如item=bed对象
# 判断,家具对象所需要占用空间
needArea = item.getUsedArea()
if self.area >= needArea:
# 可以摆放,追加到列表中,房子面积-家县占用面积
self.items.append(item)
self.area -= needArea
print(f'家具成功摆放')
else:
# 家具占用面积 > 房子剩余面积,所以无法摆放
print('很抱歉,由于此家具占用面积大于房子剩余面积,此家具无法摆放!')
def __str__(self):
msg = f'房子坐落于{self.addr},剩余面积{self.area}'
if len(self.items) > 0:
msg += ',目前家里摆放的家具主要有:'
for i in self.items:
msg = msg + i.getName() + ','
return msg
class Bed(object):
# 为家具对象定义属性
def __init__(self, name, area):
self.__name = name
self.__area = area
# 定义接口访问数据
def getUsedArea(self):
return self.__area
def getName(self):
return self.__name
def __str__(self):
return f'家具名称{self.__name},占用面积{self.__area}'
bed = Bed('席梦思', 5)
table = Bed('桌子',20)
# print(bed)
myhouse = House('珠江新城', 120)
myhouse.addItem(bed)
myhouse.addItem(table)
print(myhouse)
6. 面向对象的三大特性
面向对象有哪些特性
封装性、继承性、多态性
6.1 Python中的封装
在Python代码中,封装有两层含义
① 把现实世界中的主体中的属性和方法书写到类的里面的操作即为封装
class Person():
# 封装属性
#封装方法
② 封装可以为属性和方法添加为私有权限
6.1.1 封装中的私有属性和私有方法
在面向对象代码中,我们可以把属性和方法分为两大类:
公有(属性、方法) 私有(属性、方法)
Python:公有(属性、方法),私有(属性、方法)Java:公有(属性、方法),受保护(性、方法),私有(性、方法)
公有属性和公有方法:无论在类的内部还是在类的外部我们都可以对属性和方法进行操作。
但是有些情况下,我们不希望在类的外部对类内部的属性和方法进行操作。我们就可以把这个属性或方法封装成私有形式。
6.1.2 私有属性的访问限制
设置私有属性和私有方法的方式非常简单:在属性名和方法名 前面 加上两个下划线__即可。
基本语法:
class Girl():
def __init__(self, name):
self.name = nameself.__age = 18 #私有属性
xiaomei = Girl('小美')
print(xiaomei.name)
print(xiaomei.__age) # 报错,提示Girl对象没有__age属性
在实际工作中,理论上所有的属性都应该封装为私有形式,保证据的安全!
class Person(object):
# 属性
def __init__(self, name):
self.__name = name
self.__age = 18
# 在类的内部,私有属性是可以访问的(针对外部无法直接调用而已)
# 接口
def getName(self):
return self.__name
def getAge(self):
return self.__age
# 实例化产生对象
p1 = Person('小美')
print(p1.getAge()) #18
6.2. Python 中的继承
在Python代码中,为(实现代码重用 =>体现共性与个性的问题,可以通过继承来实现重用关系如果A类继承了B中的所有公共属性和公共方法
基本语法:
# 父类B
class B(object):
pass
# 子类A
class A(B):
passA这个类实例化的对象会自动拥有B类的中所有公共属性和公共方法
注意事项
在Python中,所有类默认继承object类,object类是顶级类或基类;其他子类叫做派生类。
示例:
class Person(object):
def eat(self):
print('吃')
def run(self):
print('跑')
class Stuent(Person):
pass
stu = Stuent()
stu.eat() #输出吃
继承:一个类从另一个已有的类获得其成员的相关特性,就叫作继承!
派生:从一个已有的类产生一个新的类,称为派生!
很显然,继承和派生其实就是从不同的方向来描述的相同的概念而已,本质上是一样的!
父类:也叫作基类,就是指已有被继承的类!
子类:也叫作派生类或扩展类
扩展:在子类中增加一些自己特有的特性,就叫作扩展,没有扩展,继承也就没有意义了!单继承:一个类只能继承自一个其他的类,不能继承多个类,单继承也是大多数面向对象语言的特性!
多继承:一个类同时继承了多个父类,(C++、Python等语言都支持多继承)
6.2.1 单继承
一个类只能继承自一个其他的类,不能继承多个类。这个类会有具有父类的属性和方法
基本语法:
# 父类B
class B(object):
pass
# 子类A
class A(B):
pass
示例:
class Car(object):
def __init__(self,brand,model):
self.brand = brand
self.model = model
def run(self):
print('跑')
class Bwm(Car):
pass
bwm = Bwm('宝马','X5')
print(bwm.brand)
print(bwm.model)
bwm.run()
输出:
宝马
X5
跑
单继承特性(多层继承):
在Python继承中,如A类继承了B类,B类又继承了c类。则根据继承的传递性,则A类也会自动继承C类中所有属性和方法(公共)
名层继承也是单继承的一种延伸,简单来说:A =>B =>C,所以A自动继承(C中的所有公共属性和公共方法
class c(objecl):
def func(self):
print('我是C类中的相关方法func')
class B(C):
pass
class A(B):
pass
a = A()a.func()
6.2.2 多继承
#汽油车类
class GasolineCar(object):
def run_with_gasoline(self):
print('i can run with gasoline!')
# 电动车类
class ElectricCar(object):
def run_with_electric(self):
print('i can run with electric!')
# 混动汽车
class Hybridcar(ElectricCar,GasolineCar):
pass
benz = Hybridcar()
benz.run_with_gasoline()
benz.run_with_electric()
# 输出:
# i can run with gasoline!
# i can run with electric!
子类扩展:重写父类属性和方法
重写也叫作 覆盖就是当子类成员与父类成员名字相同的时候,从父类继承下来的成员会重新定义!
此时,通过子类实例化出来的对象访问相关成员的时候,真正其作用的是子类中定义的成员!
class Father(object):
属性
方法
class Son(Father):
父类属性和方法
自己的属性和方法(如果子类中的属性和方法与父类中的属性或方法同名,则子类中的属性或方法会对父类中同名的属性或方法进行覆盖(重写))
扩展:子类继承父类的同时,达可以编写一些属于自己的属性和方法。甚全重写父类属性或方法,我们把这种形式就称之为扩展
继承意义:(1)实现代码重用(2)子类应该在继承的同时,拥有自己的特性(扩展)
案例:
class Animal(object):
def eat(self):
print('i can eat food!')
def call(self):
print('i can call!')
class Dog(Animal):
# 重写父类的call方法
def call(self):
print('i can 汪汪汪!')
class Cat(Animal):
# 重写父类的call方法
def call(self):
print('i can 喵喵喵!')
dog = Dog()
dog.eat()
dog.call()
cat = Cat()
cat.eat()
cat.call()
输出:
i can eat food!
i can 汪汪汪!
i can eat food!
i can 喵喵喵!
super()调用父类属性和方法
调用父类属性或方法,完整写法: super(当前类名,self).属性或方法(),
在Python3以后super():版本中,调用父类的属性和方法我们只需要使用 super().属性或super().方法名()就可以完成调用
class Car(object):
# 定义一些公共属性
def __init__(self,brand, model, color):
self.brand = brand
self.model = model
self.color = color
#定义一个公共方法
def run(self):
print('i can run!')
#汽油车类
class GasolineCar(Car):
# 修改父类方法
def run(self):
print('i can run with gasoline!')
# 电动车类
class ElectricCar(Car):
# 修改父类属性
def __init__(self,brand, model, color,battey):
super().__init__(brand, model, color)
self.battey = battey
# 修改父类方法
def run(self):
super().run()
print('i can run with ElectricCar!')
tesla = ElectricCar('Tesla','model 3','白色',30000)
print(tesla.brand,tesla.battey) #Tesla 30000
tesla.run() # i can run! i can run with ElectricCar!
6.3 多态
定义:多态是一种使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果
什么是多态?简单来说就是一种事物,随着传入对象的不同,可以返回多种形态。
① 多态依赖继承
② 子类方法必须要重写父类方法
好处:调用灵活,有了多态,更容易编写出通用的代码,做出通用的编程,以适应需求的不断变化!
案例:
class Fruit(object):
def makejuice(self):
pass
class Apple(Fruit):
def makejuice(self):
print('i can make apple juice')
class Orange(Fruit):
def makejuice(self):
print('i can make Orange juice')
class Banana(Fruit):
def makejuice(self):
print('i can make Banana juice')
# 定义一个公共接口 =>多态特性 => 要求传入一个对象作为参数
def service(obj):
obj.makejuice()
apple = Apple()
orange = Orange()
banana = Banana()
service(apple) #i can make apple juice
7. MRO属性或MRO方法:方法解析顺序
MRO(Method Resolution Order):方法解析顺序,我们可以通过 类名.__mro__或 类名.mro()获得“类的层次结构”,方法解析顺序也是按照这个“类的层次结构”寻找到。
了解一下以上代码的继承关系,到底HybridCar优先继承哪个类中的所有公共属性和公共方法呢?
#汽油车类
class GasolineCar(object):
def run(self):
print('i can run with gasoline!')
# 电动车类
class ElectricCar(object):
def run(self):
print('i can run with electric!')
# 混动汽车
class Hybridcar(ElectricCar,GasolineCar):
pass
# 了解一下以上代码的继承关系,到底HybridCar优先继承哪个类中的所有公共属性和公共方法呢?
print(Hybridcar.__mro__)
输出:(<class '__main__.Hybridcar'>, <class '__main__.ElectricCar'>, <class '__main__.GasolineCar'>, <class 'object'>)
8. 对象转换为字典
把对象转换为dict字典格式=>__dict__
只能用于对象属性
class A(objecl):
a = 0
def __init__(self):self.b =1
aa = A()
#返回实例属性和值组成的字典
print(aa.__dict__) #{b:1}
9.案例:学生管理系统-面向对象
上述文件分别是 启动文件,学生对象,管理系统,数据保存地址
源码如下:
main.py
from SudentManager import StudentManager
if __name__ == '__main__':
sm = StudentManager()
sm.start()
Student.py
class Student(object):
# 对象属性
def __init__(self,name,age,mobile):
self.name = name
self.age = age
self.mobile = mobile
# 方法
def __str__(self):
return f'姓名:{self.name},年龄:{self.age},电话:{self.mobile}'
if __name__ == '__main__':
stu = Student('张三','12','10086')
print(stu)
StudentManager.py
from Student import Student
class StudentManager(object):
# 定义属性保存所有学生信息 => [s1,s2,s3]
def __init__(self):
self.students = []
# 封装menu()方法 => 静态方法
@staticmethod
def menu():
print('-' * 40)
print('欢迎使用学生管理系统V2.0')
print('【1】添加学员信息')
print('【2】删除学员信息')
print('【3】修改学员信息')
print('【4】查询学员信息')
print('【5】遍历所有学员信息')
print('【6】保存数据')
print('【0】退出系统')
print('-' * 40)
def add_student(self):
# 接收信息
name = input('请输入需要添加学生的姓名:')
age = input('请输入需要添加学生的年龄:')
mobile = input('请输入需要添加学生的电话:')
s = Student(name, age, mobile)
self.students.append(s) # [s1,s2,s3]
print(s)
print('信息录入成功!')
def del_student(self):
name = input('请输入需要删除学生的姓名:')
for i in self.students:
if i.name == name:
self.students.remove(i)
print(f'{name}同学已删除')
break
else:
print(f'未找到{name}同学信息')
def edit_student(self):
name = input('请输入需要修改学生的姓名:')
for i in self.students:
if i.name == name:
i.name = input('请输入修改后的姓名')
i.age = input('请输入修改后的年龄')
i.mobile = input('请输入修改后的电话')
print('修改成功')
break
else:
print(f'未找到{name}同学信息')
def select_student(self):
name = input('请输入需要查询学生的姓名:')
for i in self.students:
if i.name == name:
print(i)
break
else:
print(f'未找到{name}同学信息')
def print_students(self):
if self.students:
for i in self.students:
print(i)
else:
print('暂未有信息')
# print(self.students)
def save_students(self):
f = open('./students.txt','w',encoding='UTF-8')
f.write(str([i.__dict__ for i in self.students]))
f.close()
print('保存成功')
def load_data(self):
f =open('./students.txt','r',encoding='UTF-8')
content = f.read() #str
if not content:
return
data= eval(content) #转换为 List
# print(type(data))
# print(type(content))
self.students = [Student(i['name'],i['age'],i['mobile']) for i in data]
# 定义启动方法
def start(self):
# 将txt文件数据加载
self.load_data()
# 给系统添加死循环
while True:
# 打印系统功能菜单 = > 输出自身信息,输出可以实现的相关功能
StudentManager.menu()
# 提示执行功能
user_num = int(input('请输入您要执行的功能编号:'))
# 判断操作
if user_num == 1:
self.add_student()
elif user_num == 2:
self.del_student()
elif user_num == 3:
self.edit_student()
elif user_num == 4:
pass
elif user_num == 5:
self.print_students()
elif user_num == 6:
self.save_students()
elif user_num == 0:
print('退出成功')
break
else:
print('输入有误')