导图社区 python_面向对象编程
Python面向对象编程思维导图中包括了类、对象、继承、多态、封装等基本概念和相关语法。学习这些概念和语法可以帮助您更好地理解和应用Python的面向对象编程功能。 购买这个思维导图的优势如下: 省时省力:这个思维导图可以帮助您更快地掌握Python面向对象编程的基本概念和语法,避免花费大量时间和精力在学习这些基础知识上。 高效学习:这个思维导图采用了图形化的方式呈现知识点,让您更容易理解和记忆。 灵活性:这个思维导图可以轻松地打印或在电子设备上查看,让您随时随地都可以学习Python面向对象编程。 实用性:这个思维导图还包括了一些实用的代码示例,让您更深入地理解Python面向对象编程的应用。
编辑于2023-08-01 17:39:27 山西经典好书,精准的可以翻译为电影语言的技法,场面调度 剪辑的经典之作,这本书干货很多,我对每个部分进行了总结,对部分内容进行了补充,对语法进行了重点标注,看不懂的朋友辅助例子看,还是很容易理解的。有些朋友说混乱的例子让很多人都读不下去,各种越轴,各种抽象,但是视听语法没问题,其实看不懂就是对重点语法没理解,例子不是重点,只是作者为了帮助我们理解视听语言的中心语法,希望对于喜欢这本干货的朋友有所帮助!
很多人都会觉得年终总结很难,因为要整理很多数据,还要写很多报告。有时候,他们甚至不知道应该从哪里开始。 不过,好消息来了!我们有一套神奇的“年终总结模板”,可以帮助你们轻松完成这个任务。
机会在哪里?用户痛点在哪?7个来源帮你看清本质.人人都知道创新的重要性,但关键问题是,该如何进行创新呢?随本脑图看看吧!
社区模板帮助中心,点此进入>>
经典好书,精准的可以翻译为电影语言的技法,场面调度 剪辑的经典之作,这本书干货很多,我对每个部分进行了总结,对部分内容进行了补充,对语法进行了重点标注,看不懂的朋友辅助例子看,还是很容易理解的。有些朋友说混乱的例子让很多人都读不下去,各种越轴,各种抽象,但是视听语法没问题,其实看不懂就是对重点语法没理解,例子不是重点,只是作者为了帮助我们理解视听语言的中心语法,希望对于喜欢这本干货的朋友有所帮助!
很多人都会觉得年终总结很难,因为要整理很多数据,还要写很多报告。有时候,他们甚至不知道应该从哪里开始。 不过,好消息来了!我们有一套神奇的“年终总结模板”,可以帮助你们轻松完成这个任务。
机会在哪里?用户痛点在哪?7个来源帮你看清本质.人人都知道创新的重要性,但关键问题是,该如何进行创新呢?随本脑图看看吧!
面向对象编程
面向对象基础
理解面向对象
面向对象是一种抽象化的编程思想,很多编程语言中都有的一种思想。
例如:洗衣服
思考:几种途径可以完成洗衣服?
答:手洗和机洗。
手洗:找盆-放水-加洗衣粉-浸泡-搓洗-拧干水-倒水-漂洗N次-拧干-晾晒。
机洗:打开洗衣机-放衣服-加洗衣粉-按下开始按钮-晾晒。
思考:对比两种洗衣服途径,同学们发现了什么?
答:机洗更简单
思考:机洗,只需要找到一台洗衣机,加入简单操作就可以完成洗衣服的工作,而不需要关心洗衣机内部发生了什么事情。
总结:面向对象就是将编程当成是一个事物,对外界来说,事物是直接使用的,不用去管他内部的情况。而编程就是设置事物能够做什么事。
理解类和对象
类和对象
思考:洗衣机洗衣服描述过程中,洗衣机其实就是一个事物,即对象,洗衣机对象哪来的呢?
答:洗衣机是由工厂工人制作出来。
思考:工厂工人怎么制作出的洗衣机?
答:工人根据设计师设计的功能图纸制作洗衣机。
总结:图纸→洗衣机→洗衣服。
在面向对象编程过程中,有两个重要组成部分:类(图纸)和对象(洗衣机)。
类和对象的关系:用类去创建(实例化)一个对象。
理解类和对象
类
类是对一系列具有相同特征和行为的事物的统称,是一个抽象的概念,不是真实存在的事物。
特征即是属性
行为即是方法
类比如是制造洗衣机时要用到的图纸,也就是说类是用来创建对象。
对象
对象是类创建出来的真实存在的事物,例如:洗衣机。
注意:开发中,先有类,再有对象。
在编程中,特征是变量,行为(功能)是函数
面向对象实现方法
定义类
Python2中类分为:经典类和新式类
语法: class 类名(): 代码......
注意:类名要满足标识符命名规则,同时遵循大驼峰命名习惯。
创建对象
对象又名实例
语法
对象名=类名()
self
self指的是调用该函数的对象。
形参
需求:洗衣机,功能:能洗衣服
添加和获取对象属性
属性即是特征,比如:洗衣机的宽度、高度、重量...
对象属性既可以在类外面添加和获取,也能在类里面添加和获取。
类对象属性
类外面添加对象属性
语法
对象名.属性名=值
例子
haier1.width =500 haier1.height = 800
类外面获取对象属性
语法
对象名.属性名
例子
print(f'haier1洗衣机的宽度是(haier1.width') print(f'haier1洗衣机的高度是{haierl.height}')
类里面获取对象属性
语法
se1f.属性名
例子
#定义类 class Washer(): def print_info(self): #类里面获取实例属性 print(f'haien1洗衣机的宽度是{self.width}') print(f'haier1洗衣机的高度是{self.height}') #创建对象 haier1 Washer() #添加实例属性 haier1.width =500 haier1.height 800
魔法方法
在Python中,__xx__()的函数叫做魔法方法,指的是具有特殊功能的函数.
__init__()函数
思考:洗衣机的宽度高度是与生俱来的属性,可不可以在生产过程中就赋予这些属性呢?
答:理应如此
__init__()
作用:初始化对象
class Washer(): #定义init,添加实例属性 definit_(self): #添加实例属性 self.width =500 self.height 800 def print_info(self): #类里面调用实例属性 print(f'洗衣机的宽度是{self.width},高度是{self.height)') haier1 Washer() haier1.print_info()
注意 __init__()方法,在创建一个对象时默认被调用,不需要手动调用 __init__(self)中的self参数,不需要开发者传递,python解释器会自动把当前的对象引用传递过去。
带参数的__init__()函数
思考:一个类可以创建多个对象,如何对不同的对象设置不同的初始化属性呢?
答:传参数
class Washer(): definit __init__(self,width,height): self.width width self.heightheight def print_info(self): print(f'洗衣机的宽度是{self.width}') print(f'洗衣机的高度是{self.height}') haier1 Washer(10,20) haier1.print_info() haier2 Washer(30,40) haier2.print_info()
__str__()函数
当使用print输出对象的时候,默认打印对象的内存地址。如果类定义__str__方法,那么就会打印从在这个方法中 return 的数据。
class Washer(): def_init_(self,width,height): self.width width self.heightheight def _str_(self): return'这是海尔洗衣机的说明书' haier1 Washer(10,20) #这是海尔洗衣机的说明书 print(haier1)
__del__()
当删除对象时,python解释器也会默认调用__del__()方法.
class Washer(): definit_(self,width,height): self.width width self.height height def _del_(self): print(f'{self力对象已经被删除') haier1 Washer(10,20) # <_main_.Washer object at 0xe000026118223278>对象已经被删除 del haier1
综合应用
烤地瓜
需求主线
1.被烤的时间和应对的地瓜状态
0-3分钟:生的
3-5分钟:半生不熟
5-8分钟:熟的
超过8分钟:烤糊了
2.添加的调料
用户可以按自己的意愿添加调料
步骤分析
需求涉及一个事物:地瓜,故案例涉及一个类:地瓜类。
定义类
地瓜的属性
定义类,初始化
被烤的时间
self.cook_time += time的目的是:考虑中途取出来的情况,算出每次烤的时间的累加
地瓜的状态
添加的调料
地瓜的方法
被烤
用户根据意愿设定每次烤地瓜的时间
判断地瓜被烤的总时间是在哪个区间,修改地瓜状态
添加调料
用户根据意愿设定添加的调料
将用户添加的调料存储
显示对象信息
代码实现
搬家具
需求:将小于房子剩余面积的家具摆放到房子中
步骤分析
:需求涉及两个事物:房子 和 家具,故被案例涉及两个类:房子类 和 家具类。
定义类
家具类
家居名称
家具占地面积
房子类
实例属性
房子地理位置
房子占地面积
房子剩余面积
房子内家具列表
实例方法
容纳家具
显示房屋信息家具类家具名称家具占地面积
创建对象并调用相关方法
代码实现
继承
继承的概念
在 Python 中,继承是面向对象编程中的一个重要概念,它允许子类继承父类的属性和方法,并且可以在子类中添加或修改属性和方法。在 Python 中,继承通过定义一个类并指定一个父类来实现。
经典类
不由任意内置类型派生出的类,称之为经典类。python2使用
class类名: 代码
新式类
python3使用
class类名(object): 代码
object是默认状态下是所有类的顶级类(基类)
体验继承
Python面向对象的继承指的是多个类之间的所属关系,即子类默认继承父类的所有属性和方法,具体如下:
#父类A class A(object): definit_(self): self.num 1 def info_print(self): print(self.num) #子类B class B(A): pass result B() result.info_print() #1
在Python中,所有类默认继承object类,object类是顶级类或基类;其他子类叫做派生类。
单继承
定义
一个父类继承给一个子类
故事主线:一个煎饼果子老师傅,在煎饼果子界摸爬滚打多年,研发了一套精湛的摊煎饼果子的技术。师父要把这套技术传授给他的唯一的最得意的徒弟。
分析:徒弟是不是要继承师父的所有技术?
#1.师父类 class Master(object): def_init_(self): self.kongfu='[古法煎饼果子配方]' def make_cake(self): print(f'运用{self.kongfu制作煎饼果子') #2.徒弟类 class Prentice(Master): pass #3.创建对象daqiu daqiu Prentice() #4.对象访问实例属性 print(daqiu.kongfu)
多继承
故事推进:daqiu是个爱学习的好孩子,想学习更多的煎饼果子技术,于是,在百度搜索到黑马程序员,报班学习煎饼果子技术。
所谓多继承意思就是一个类同时继承了多个父类。
#创建师父类 class Master(object): def_init_(self): self.kongfu="古法煎饼果子" def make_cake(self): print(f"调用{self.kongfu}制作煎饼果子") #创建学校类 class School(object): def _init_(self): se1f.kongfu="[黑马煎饼果子配方]" def make_cake(self): print(f"运用{self.kongfu}制作煎饼果子") #创建徒弟类 class Prentice(School,Master): pass daqiu Prentice() print(daqiu.kongfu) daqiu.make_cake()
注意:当一个类有多个父类的时候,默认使用第一个父类的同名属性和方法。
子类重写父类的同名属性和方法
属性故事:daqiu掌握了师父和培训的技术后,自己潜心钻研出自己的独门配方的一套全新的煎饼果子技术。
#创建师父类 class Master(object): def _init_(self): self.kongfu="古法煎饼果子" def make_cake(self): print(f"调用[self.kongfu}制作煎饼果子") #创建学校类 class School(object): def _init_(self): self.kongfu="[黑马煎饼果子配方]" def make_cake(self): print(f"运用[self.kongfu}制作煎饼果子") #独创配方 class Prentice(School,Master): def _init_(self): self.kongfu="[独创煎饼果子配方]" def make_cake(self): print(f"运用[self.kongfu}制作煎饼果子") daqiu Prentice() print(daqiu.kongfu) daqiu.make_cake()
拓展-mro顺序
快速查看一个类的层级关系
print(Prentice.__mro__)
子类调用父类的同名属性和方法
故事:很多顾客都希望也能吃到古法和黑马的技术的煎饼果子。
#创建师父类 class Master(object): def_init_(self): self.kongfu="古法煎饼果子" def make_cake(self): print(f"调用[self.kongfu制作煎饼果子") #创建学校类 class School(object): def_init_(self): se1f.kongfu="[黑马煎饼果子配方]" def make_cake(self): #加自己初始化的原因:如果不加自己的初始化,kongfu属性值是上一次调用的init内的kongfu属性值 print(f"运用{self.kongfu}制作煎饼果子") #独创配方 class Prentice(School,Master): def_init_(self): self.kongfu="[独创煎饼果子配方]" def make_cake(self): self.__init_() print(f"运用{self.kongfu}制作煎饼果子") #子类调用父类的同名方法和属性:把父类的同名属性和方法再次封装 def make_master_cake(self): #再次调用初始化的原因:这里想要调用父类的同名方法和属性,属性在it初始化位置,所以需要再次调用 Master._init_(self) #父类类名.函数() Master.make_cake(self) def make_school_cake(self): School.__init_(self) School.make_cake(self) daqiu Prentice() print(daqiu.kongfu) daqiu.make cake() daqiu.make_master_cake() daqiu.make_cake()
多层继承
故事:N年后,daqiu老了,想要把所有技术传承给自己的徒弟。
#创建师父类 class Master(object): def __init_(self): self.kongfu="古法煎饼果子" def make cake(self): print(f"调用{self.kongfu}制作煎饼果子") #创建学校类 class School(object): def _init_(self): self.kongfu="[黑马煎饼果子配方]" def make_cake(self): #加自己初始化的原因:如果不加自己的初始化,kongfu属性值是上一次调用的init内的kongfu属性值 print(f"运用{self.kongfu}制作煎饼果子") #独创配方 class Prentice(School,Master): def _init_(self): self.kongfu="[独创煎饼果子配方]" def make_cake(self): self.__init_() print(f"运用{self.kongfu)制作煎饼果子") #子类调用父类的同名方法和属性:把父类的同名属性和方法再次封装 def make_master_cake(self): #再次调用初始化的原因:这里想要调用父类的同名方法和属性,属性在iit初始化位置,所以需要再次调用 Master._init_(self) #父类类名.函数() Master.make_cake(self) def make_school_cake(self): School.__init_(self) School.make_cake(self) #徒孙类 class Tunsun(Prentice): pass xiaoqiu Tunsun() xiaoqiu.make_cake() xiaoqiu.make_master_cake() xiaoqiu.make_school_cake()
super()调用父类方法
作用
调用父类方法
注意:使用super()可以自动查找父类。调用顺序遵循__mro__类属性的顺序。比较适合单继承使用。
# 创建师父类 class Master(object): def __init__(self): self.kongfu = "古法煎饼果子" def make_cake(self): print(f"调用{self.kongfu}制作煎饼果子") # 创建学校类 class School(Master): def __init__(self): self.kongfu = "[黑马煎饼果子配方]" def make_cake(self): print(f"运用{self.kongfu}制作煎饼果子") # 2.1 super() 带参数写法 # super(School, self).__init__() # super(School, self).make_cake() #2.2super 无参数写法 super().__init__() super().make_cake() # 独创配方 class Prentice(School): def __init__(self): self.kongfu = "[独创煎饼果子配方]" def make_cake(self): self.__init__() print(f"运用{self.kongfu}制作煎饼果子") def make_master_cake(self): Master.__init__(self) Master.make_cake(self) def make_school_cake(self): School.__init__(self) School.make_cake(self) def make_old_cake(self): # 2.1 super(当前类名, self).函数() 带参数写法 # super(Prentice, self).__init__() # super(Prentice, self).make_cake() # 2.2 super 无参数写法 super().__init__() super().make_cake() daqiu = Prentice() daqiu.make_old_cake()
私有属性和私有方法
私有权限
定义私有属性和方法
在Python中,可以为实例属性和方法设置私有权限,即设置某个实例属性或实例方法不继承给子类。
故事:daqiu把技术传承给徒弟的同时,不想把自己的钱(2000000个亿)继承给徒弟,这个时候就要为 钱 这个实例属性设置私有权限。
设置私有权限的方法:在属性名和方法名 前面 加上两个下划线。
语法
#定义私有属性 self.__money 200000 #定义私有方法 definfo__print(self): print(self.kongfu) print(self.money)
获取和修改私有属性值
在Python中,一般定义函数名 get_xx 用来获取私有属性,定义 set_xx 用来修改私有属性值。
class Prentice(School, Master): def __init__(self): self.kongfu = "[独创煎饼果子配方]" self.__money = 200000 # 定义函数:获取私有属性值 get_xx def get_money(self): return self.__money # 定义函数:修改私有属性值 set_xx def set_money(self): self.__money = 500
多态 类方法 类属性
面向对象三大特性
封装
将属性和方法书写到类的里面的操作即为封装
封装可以为属性和方法添加私有权限
继承
子类默认继承父类的所有属性和方法
子类可以重写父类属性和方法
多态
传入不同的对象,产生不同的结果
了解多态
多态指的是一类事物有多种形态,(一个抽象类有多个子类,因而多态的概念依赖于继承)。
定义:多态是一种使用对象的方式,子类重写父类方法,调用不同子类对象的相同父类方法,可以产生不同的执行结果
好处:调用灵活,有了多态,更容易编写出通用的代码,做出通用的编程,以适应需求的不断变化!
实现步骤: 定义父类,并提供公共方法 定义子类,并重写父类方法 创建对象,调用不同的功能,传入不同的对象,观察执行的结果.
体验多态
#创建一个狗的父类 class Dog(object): def_init_(self)->None: pass def work(self): print("指哪打哪") #创建一个狗的子类 class Armdog(Dog): definit(self)->None: pass def work(self): print("追击敌人") #创建另一个狗的子类 class Drugdog(Dog): def init (self)->None: pass def work(self): print("寻找毒品") #创建一个人的类 class Person(object): def init (self)->None: pass def work with dog(self,dog): dog.work() ad Armdog() dd Drugdog() daqiu Person() daqiu.work_with_dog(ad) daqiu.work_with_dog(dd)
类属性和实例属性
类属性
设置和访问类属性
类属性就是 类对象 所拥有的属性,它被 该类的所有实例对象 所共有。
类属性可以使用 类对象 或 实例对象 访问。
class Dog(object):#定义类 touch = 10 #设置类属性 wangcai Dog() #访问类属性 xiaohei Dog() print(Dog.touch) #通过类访问类属性 print(wangcai.touch)#通过对象访问类属性 print(xiaohei.touch)#通过对象访问类属性
类属性的优点
记录的某项数据 始终保持一致时,则定义类属性。
实例属性 要求 每个对象 为其 单独开辟一份内存空间 来记录数据,而 类属性 为全类所共有,仅占用一份内存,更加节省内存空间。
修改类属性
类属性只能通过类对象修改,不能通过实例对象修改,如果通过实例对象修改类属性,表示的是创建了,一个实例属性。
class Dog(object):#定义类 touch 10 #设置类属性 wangcai Dog() #访问类属性 xiaohei Dog() #1.通过类修改类属性(类.类属性值)=值 Dog.touch =20 print(Dog.touch) print(wangcai.touch) print(xiaohei.touch) #2.测试通过对象修改类属性 #wangcai.touch=2gg#创建了一个实例属性 print(Dog.touch)10 print(wangcai.touch)200 # print(xiaohei.touch)
类方法和静态方法
类方法
类方法特点
需要用装饰器@classmethod来标识其为类方法,对于类方法,第一个参数必须是类对象,一般以cls 作为第一个参数。
类方法使用场景
当方法中需要使用类对象(如访问私有类属性等)时,定义类方法
类方法一般和类属性配合使用
class Dog(object):#定义类 touch 10 #设置私有类属性 #定义类方法 @classmethod def get_touch(cls): return cls.__touch wangcai Dog() result wangcai.get_touch() print(result)
静态方法
静态方法特点
需要通过装饰器@staticmethod来进行修饰,静态方法既不需要传递类对象也不需要传递实例对象(形参没有self/cls)。
静态方法 也能够通过 实例对象 和 类对象 去访问。
静态方法使用场景
当方法中 既不需要使用实例对象(如实例对象,实例属性),也不需要使用类对象(如类属性、类方法、创建实例等)时,定义静态方法
取消不需要的参数传递,有利于 减少不必要的内存占用和性能消耗
#1.定义类,定义静态方法 class Dog(object): @staticmethod def info_print(): print("这是一个静态方法") #2.创建对象 wangcai Dog() #3.调用静态方法:类和对象 wangcai.info_print() #这是一个静态方法 Dog.info print()#这是一个静态方法
异常
了解异常
当检测到一个错误时,解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的"异常"。
例如:以r方式打开一个不存在的文件。
open('test.txt','r')
FileNotfoundError叫做异常类型
[Errno 2]No such file or directory:'test.txt叫做异常信息
异常的写法
语法
try: 可能发生错误的代码 except: 如果出现异常执行的代码
快速体验
需求:尝试以r模式打开文件,如果文件不存在,则以w方式打开
try: f open("test.txt","r") except: f open("test.txt","w")
捕获异常
捕获指定异常类型
语法
try: 可能发生错误的代码 except异常类型: 如果捕获到该异常类型执行的代码
体验
try print(num) except NameError: print("有错误")
注意:
1.如果尝试执行的代码的异常类型和要捕获的异常类型不一致,则无法捕获异常。
2.一般try下方只放一行尝试执行的代码。
捕获多个指定异常
不能确定是哪个异常时使用,当捕获多个异常时,可以把要捕获的异常类型的名字,放到except后,并使用元组的方式进行书写。
try: print(1/0) except (NameError,ZeroDivisionError): print('有错误')
捕获异常描述信息
try: print(num) except (NameError,ZeroDivisionError)as result: print(result)
捕获所有异常
Exception是所有程序异常类的父类。
try: print(num) except Exception as result: print(result)
异常的else
else表示的是如果没有异常要执行的代码。
语法
try: print(1) except Exception as result: print(result) else: print('我是else,是没有异常的时候执行的代码')
异常finally
finally表示的是无论是否异常都要执行的代码,例如关闭文件。
语法
try: f = open('test.txt','r') except Exception as result: f = open('test.txt','w') else: print('没有异常,真开心') finally: f.close()
异常的传递
体验异常传递
需求:1. 尝试只读方式打开test.txt文件,如果文件存在则读取文件内容,文件不存在则提示用户即可。2.读取内容要求:尝试循环读取内容,读取过程中如果检测到用户意外终止程序,则except捕获异常并提示用户。
import time try: f open("test.txt","r") try: while True: content f.readline() if len(content)==0: break time.sleep(2) print(content) except: #如果在读取文件的过程中,产生了异常,那么就会捕获到 #比如按下了ctr1+c print("意外终止了读取数据") finally: f.close() print("关闭文件") except: print("该文件不存在")
自定义异常
在Python中,抛出自定义异常的语法为 raise 异常类对象。
作用
将不满足程序需求的代码抛出异常
需求:密码长度不足,则报异常(用户输入密码,如果输入的长度不足3位,则报错,即抛出自定义异常,并捕获该异常)。
""需求:密码长度不足,则报异常(用户输入密码,如果输入的长度不足3位, 则报错,即抛出自定义异常,并捕获该异常)。 1.创建异常类 2.抛出异常 3.捕获该异常"" class ShortInputError(Exception):#程序异常类的父类是Exception def_init_(self,length,min_len): self.length length self.min_len min_len def _str_(self): return f'"您输入的长度是[self.length},不能少于(self.min_len}" def main(): try: con=input("请您输入密码:") if len(con)<3: raise ShortInputError(len(con),3) except Exception as result: print(result) else: print("密码输入已经完成") main()
总结
模块和包
模块
Python模块(Module),是一个Python文件,以.py结尾,包含了Python对象定义和Python语句。模块能定义函数,类和变量,模块里也能包含可执行的代码。
导入模块
导入模块的方式
import模块名
语法
#1.导入模块 import模块名 import模块名1,模块名2.·. #2.调用功能 模块名.功能名()
体验
import math print(math.sqrt(9)) #3.0
from模块名import功能名
语法
from模块名import功能1,功能2,功能3..
体验
from math import sqrt print(sqrt(9))
from模块名import *
语法
from模块名import *
体验
import模块名as别名 from模块名import功能名as别名
语法
#模块定义别名 import模块名as别名 #功能定义别名 from模块名import功能as别名
如果定义了别名,就只能使用别名,不能用模块名
体验
制作模块
在Python中,每个Python文件都可以作为一个模块,模块的名字就是文件的名字。也就是说自定义模块名必须要符合标识符命名规则。
定义模块
需求:新建一个Python文件,命名为my_module1.py,并定义testA函数。
体验
测试模块
在实际开中,当一个开发人员编写完一个模块后,为了让模块能够在项目中达到想要的效果,这个开发人员会自行在py文件中添加一些测试信息.,例如,在 my_module1.py 文件中添加测试代码。
def testA(a,b): print(a b) testA(1,1)
此时,无论是当前文件,还是其他已经导入了该模块的文件,在运行的时候都会自动执行testA函数的调用。解决办法如下:
调用模块
import my_module1 my_module1.testA(1,1)
模块定位顺序
当导入一个模块,Python解析器对模块位置的搜索顺序是:
1.当前目录
2.如果不在当前目录,Python则搜索在shell变量PYTHONPATH下的每个目录。
3.如果都找不到,Python会察看默认路径。UNIX下,默认路径一般为usr/local/Iib/python/
模块搜索路径存储在system模块的sys.path变量中。变量里包含当前目录,PYTHONPATH和由安装过程决定的默认目录。
注意
自己的文件名不要和已有模块名重复,否则导致模块功能无法使用
使用from模块名import功能的时候,如果功能名字重复,调用到的是最后定义或导入的功能.
__all__列表
如果一个模块文件中有__all__变量,当使用from xxx import *导入时,只能导入这个列表中的元素
my_module1模块代码
_all_=['testA'] def testA(): print('testA') def testB(): print('testB')
导入模块的文件代码
from my_modulel import testA() testB()
testA Traceback (most recent call last): Fi1e"C:Users/黑马程员/Desktop/code/hm5_al1列k.py",1ine6,in<module> testB() NameError:name 'testB'is not defined Process finished with exit code 1
模块和包
1.1 什么是模块
在计算机程序的开发过程中,随着程序代码越写越多,在一个文件里代码就会越来越长,越来越不容易维护。为了编写可维护的代码,我们把很多代码按功能分组,分别放到不同的文件里,这样,每个文件包含的代码就相对较少,很多编程语言都采用这种组织代码的方式。在Python中,一个.py文件就可以称之为一个模块(Module)。
使用模块有什么好处?
1.最大的好处是大大提高了代码的可维护性。其次,编写代码不必从零开始。当一个模块编写完毕,就可以被其他地方引用。我们在编写程序的时候,也经常引用其他模块,包括Python内置的模块和来自第三方的模块。
2,使用模块还可以避免函数名和变量名冲突。每个模块有独立的命名空间,因此相同名字的函数和变量完全可以分别存在不同的模块中,所以,我们自己在编写模块时,不必考虑名字会与其他模块冲突
模块分类模块分为三种:
内置标准模块(又称标准库)执行help('modules')查看所有python自带模块列表
第三方开源模块,可通过pip install 模块名 联网安装
自定义模块
模块导入&调用
导入模块有以下几种方式
注意:模块⼀一旦被调⽤用,即相当于执⾏了另外⼀个py文件⾥的代码
1.3 模块的查找路径
有没有发现,自己写的模块只能在当前路径下的程序里才能导入,换一个目录再导入自己的模块就报错说找不到了,这是为什么?这与导入模块的查找路径有关
输出(注意不同的电脑可能输出的不太⼀样)
你导入一个模块时,Python解释器会按照上面列表顺序去依次到每个目录下去匹配你要导入的模块名,只要在一个目录下匹配到了该模块名,就立刻导入,不再继续往后找。
注意列表第一个元素为空,即代表当前目录,所以你自己定义的模块在当前目录会被优先导入。
我们自己创建的模块若想在任何地方都能调用,那就得确保你的模块文件至少在模块路径的查找列表中。
我们一般把自己写的模块放在一个带有“site-packages"字样的目录里,我们从网上下载安装的各种第三方的模块一般都放在这个目录。
1.3 第3⽅开源模块安装
https://pypi.python.org/pypi是python的开源模块库,截止2020年5.26日,已经收录了236,269个来自全世界python开发者贡献的模块,几乎涵盖了你想用python做的任何事情。事实上每个python开发者,只要注册一个账号就可以往这个平台上传你自己的模块,这样全世界的开发者都可以容易的下载并使用你的模块。
那如何从这个平台上下载代码呢?
1. 直接在上面这个页面上点download,下载后,解压并进入目录,执行以下命令完成安装编译源码
python setup.py build 安装源码 python setup.py install
2. 直接通过pip安装pip3 install paramiko #paramiko 是模块名pip命令会自动下载模块包并完成安装。软件一般会被自动安装你python安装目录的这个子目录里
/your_python_install_path/3.6/lib/python3.6/site-packages
pip命令默认会连接在国外的python官方服务器下载,速度比较慢,你还可以使用国内的豆瓣源,数据会定期同步国外官网,速度快好多
pip install –i http://pypi.douban.com/simple/ alex_sayhi --trusted-host pypi.douban.com#alex_sayhi是模块名
-i后面跟的是豆瓣源地址一trusted-host 得加上,是通过网站https安全验证用的
使用
下载后,直接导入使用就可以,跟自带的模块调用方法无差
⼆、⼏个常⽤Python模块
2.1系统调用OS模块
os模块提供了很多允许你的程序与操作系统直接交互的功能import os
得到当前工作目录,即当前Python脚本工作的目录路径:os.getcwd() 返回指定目录下的所有文件和目录名:os.listdir() 函数用来删除一个文件:os.remove() 删除多个目录: os.removedirs (r"c: \python") 检验给出的路径是否是一个文件:os.path.isfile() 检验给出的路径是否是一个目录:os.path.isdir() 判断是否是绝对路径: os.path.isabs() 检验给出的路径是否真地存:os.path.exists() 返回一个路径的目录名和文件名:os.path.split()e.gos.path.split ('/home/swaroop/byte/code/poem.txt')结果: ('/home/swaroop/byte/code', 'poem.txt') 分离扩展名:os.path.splitext()e.g os.path.splitext('/usr/local/test.py') 结果:('/usr/local/test','.py') 获取路径名:os.path.dirname() 获得绝对路径: os.path.abspath() 获取文件名:os.path.basename() 运行shell命令: os.system() 读取操作系统环境变量HOME的值:os.getenv("HOME") 返回操作系统所有的环境变量: os.environ 设置系统环境变量,仅程序运行时有效:os.environ.setdefault('HOME','/home/alex') 给出当前平台使用的行终止符:os.linesepWindows使用'\r\n', Linux and MAC使用'\n' 指示你正在使用的平台:os.name 对于windows,它是'nt',而对于Linux/Unix用户,它是'posix' 重命名: os.rename (old, new) 创建多级目录: os.makedirs (r"c: \python\test") 创建单个目录: os.mkdir ("test") 获取文件属性: os.stat (file) 修改文件权限与时间戳: os.chmod (file) 获取文件大小: os.path.getsize (filename) 结合目录名与文件名:os.path.join(dir,filename) 改变工作目录到dirname: os.chdir(dirname) 获取当前终端的大小: os.get_terminal_size() 杀死进程:os.kill(10884,signal.SIGKILL)
2.2 time 模块
在平常的代码中,我们常常需要与时间打交道。在Python中,与时间处理有关的模块就包括:time,datetime,calendar(很少⽤,不讲),下⾯面分别来介绍。
我们写程序时对时间的处理可以归为以下3种:
时间的显示,在屏幕显示、记录日志等"2022-03-04"
时间的转换,比如把字符串格式的日期转成Python中的日期类型
时间的运算,计算两个日期间的差值等
在Python中,通常有这几种方式来表示时间:
1. 时间戳(timestamp) ,表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。例子:1554864776.161901
2.格式化的时间字符串,比如“2020-10-03 17:54"
3,元组(struct_time)共九个元素。由于Python的time模块实现主要调用C库,所以各个平台可能有所不同,mac上:time.struct_time(tm_year=2020, tm_mon=4,tm_mday=10, tm_hour=2,tm_min=53, tm_sec=15, tm_wday=2, tm_yday=100, tm_isdst=0)
索引(Index) 属性(Attribute) 值(Values) 0 tm_year(年) ⽐比如2011 1 tm_mon(⽉) 1 - 12 2 tm_mday(⽇) 1 - 31 3 tm_hour(时) 0 - 23 4 tm_min(分) 0 - 59 5 tm_sec(秒) 0 - 61 6 tm_wday(weekday) 0 - 6(0表示周⼀一) 7 tm_yday(⼀年中的第几天) 1 - 366 8 tm_isdst(是否是夏令时) 默认为-1
UTC时间
UTC (Coordinated Universal Time,世界协调时)亦即格林威治天文时间,世界标准时间。在中国为UTC+8,又称东8区。DST (Daylight Saving Time)即夏令时。
time模块的常⽤⽅法
time.localtime([secs]) :将⼀个时间戳转换为当前时区的struct_time。若secs参数未提供,则以当前时间为准。
time.gmtime([secs]) :和localtime()⽅方法类似,gmtime()⽅方法是将⼀一个时间戳转换为UTC时区(0时区)的struct_time。
time.time() :返回当前时间的时间戳。
time.mktime(t) :将⼀一个struct_time转化为时间戳。
time.sleep(secs) :线程推迟指定的时间运⾏,单位为秒。
time.strftime(format[, t]) :把⼀一个代表时间的元组或者struct_time(如由time.localtime()和time.gmtime()返回)转化为格式化的时间字符串。如果t未指定,将传⼊入time.localtime()。
举例: time.strftime(“%Y-%m-%d %X”, time.localtime()) #输出’2017-10-01 12:14:23’
time.strptime(string[, format]) :把⼀一个格式化时间字符串转化为struct_time。实际上它和strftime()是逆操作。
举例: time.strptime(‘2017-10-3 17:54’,”%Y-%m-%d %H:%M”) #输出
time.struct_time(tm_year=2017, tm_mon=10, tm_mday=3, tm_hour=17, tm_min=54,tm_sec=0, tm_wday=1, tm_yday=276, tm_isdst=-1)
字符串转时间格式对应表
最后为了容易记住转换关系,看下图
2.3 datetime模块
相比于time模块,datetime模块的接⼝则更直观、更容易调⽤
datetime模块定义了下⾯这几个类:
datetime.date:表示⽇日期的类。常⽤用的属性有year, month, day;
datetime.time:表示时间的类。常⽤用的属性有hour, minute, second, microsecond;
datetime.datetime:表示⽇日期时间。
datetime.timedelta:表示时间间隔,即两个时间点之间的⻓长度。
datetime.tzinfo:与时区有关的相关信息。(这⾥不详细充分讨论该类,感兴趣的童鞋可以参考python手册)
我们需要记住的⽅法仅以下⼏个:
1. d=datetime.datetime.now() 返回当前的datetime日期类型,d.timestamp(),d.today(),d.year,d.timetuple()等方法可以调用
2. datetime.date.fromtimestamp(322222) 把⼀一个时间戳转为datetime日期类型
3. 时间运算
>>> datetime.datetime.now()
datetime.datetime(2017, 10, 1, 12, 53, 11, 821218)
>>> datetime.datetime.now() + datetime.timedelta(4) #当前时间 +4天
datetime.datetime(2017, 10, 5, 12, 53, 35, 276589)
>>> datetime.datetime.now() + datetime.timedelta(hours=4) #当前时间+4小时
datetime.datetime(2017, 10, 1, 16, 53, 42, 876275)
4. 时间替换
>>> d.replace(year=2999,month=11,day=30)
datetime.date(2999, 11, 30)
2.4 random随机数
程序中有很多地⽅需要用到随机字符,比如登录⽹网站的随机验证码,通过random模块可以很容易⽣生成随机字符串
2.5 序列化json模块
JSON(JavaScriptObject Notation, JS对象简谱)是一种轻量级的数据交换格式。它采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得JSON 成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
Json的作用是用于不同语言接口间的数据交换,比如你把python的list、dict直接扔给javascript,它是解析不了的。2个语言互相谁也不认识。Json就像是计算机界的英语,可以帮各个语言之间实现数据类型的相互转换。
JSON⽀持的数据类型
Python中的字符串、数字、列表、字典、集合、布尔类型,都可以被序列化成JSON字符串,被其它任何编程语言解析
什么是序列化?
序列化是指把内存里的数据类型转变成字符串,以使其能存储到硬盘或通过网络传输到远程,因为硬盘或网络传输时只能接受bytes
为什么要序列化?
你打游戏过程中,打累了,停下来,关掉游戏、想过2天再玩,2天之后,游戏又从你上次停止的地方继续运行,你上次游戏的进度肯定保存在硬盘上了,是以何种形式呢?游戏过程中产生的很多临时数据是不规律的,可能在你关掉游戏时正好有10个列表,3个嵌套字典的数据集合在内存里,需要存下来?你如何存?把列表变成文件里的多行多列形式?那嵌套字典呢?根本没法存。所以,若是有种办法可以直接把内存数据存到硬盘上,下次程序再启动,再从硬盘上读回来,还是原来的格式的话,那是极好的。
用于序列化的两个模块
json,用于字符串 和 python数据类型间进行转换
Json模块也提供了四个功能:dumps、dump、loads、load,⽤用法跟pickle⼀一致
pickle,用于python特有的类型 和 python的数据类型间进行转换
pickle
模块提供了了四个功能:dumps、dump、loads、load
json vs pickle:
JSON:
优点:跨语⾔(不同语⾔言间的数据传递可⽤json交接)、体积⼩
缺点:只能⽀支持int\str\list\tuple\dict
Pickle:
优点:专为python设计,支持python所有的数据类型
缺点:只能在python中使用,存储数据占空间⼤
2.6 Excel处理模块
第3方开源模块,安装
pip install openpyxl
2.6.1 打开文件
一、创建
from openpyxl import Workbook # 实例化 wb = Workbook() # 获取当前active的sheet ws = wb.active print(sheet.title) # 打印sheet表名 sheet.title = "salary luffy" # 改sheet 名
⼆、打开已有文件
>>> from openpyxl import load_workbook >>> wb2 = load_workbook('文件名称.xlsx')
2.6.2 写数据
# 方式⼀:数据可以直接分配到单元格中(可以输⼊入公式) sheet["C5"] = "Hello 金角大王" sheet["C7"] = "Hello ⾦角⼤王2" # 方式⼆:可以附加⾏,从第⼀列开始附加(从最下⽅空白处,最左开始)(可以输⼊入多⾏) sheet.append([1, 2, 3]) # ⽅方式三:Python 类型会被自动转换 sheet['A3'] = datetime.datetime.now().strftime("%Y-%m-%d")
2.6.3 选择表
# sheet 名称可以作为 key 进⾏行行索引 ws3 = wb["New Title"] ws4 = wb.get_sheet_by_name("New Title") print(wb.get_sheet_names()) # 打印所有的sheet sheet = wb.worksheets[0] # 获得第1个sheet
2.6.4 保存表
wb.save('文件名称.xlsx')
2.6.5 遍历表数据
按行遍历
for row in sheet: # 循环获取表数据 for cell in row: # 循环获取每个单元格数据 print(cell.value, end=",") print()
按列遍历
# A1, A2, A3这样的顺序 for column in sheet.columns: for cell in column: print(cell.value,end=",") print()
遍历指定⾏&列
# 从第2行开始⾄至第5⾏,每⾏打印5列 for row in sheet.iter_rows(min_row=2,max_row=5,max_col=5): for cell in row: print(cell.value,end=",") print()
遍历指定⼏列的数据
取得第2-第5列的数据
for col in sheet.iter_cols(min_col=2,max_col=5,): for i in col: print(i.value,end=",") print()
2.6.6 删除工作表
# 方式⼀ wb.remove(sheet) # 方式⼆ del wb[sheet]
2.6.7 设置单元格样式
一、需导入的类
from openpyxl.styles import Font, colors, Alignment
⼆、字体
下面的代码指定了等线24号,加粗斜体,字体颜⾊红⾊。直接使⽤用cell的font属性,将Font对象赋值给它。
三、对齐方式
也是直接使用cell的属性aligment,这里指定垂直居中和水平居中。除了center,还可以使用right,left等等参数。
# 设置B1中的数据垂直居中和水平居中 sheet['B1'].alignment = Alignment(horizontal='center', vertical='center')
四、设置⾏高&列宽
# 第2⾏行高 sheet.row_dimensions[2].height = 40 # C列列宽 sheet.column_dimensions['C'].width = 30
2.7 邮件发送smtplib
SMTP (Simple Mail Transfer Protocol)即简单邮件传输协议,它是一组用于由源地址到目的地址传送邮件的规则,由它来控制信件的中转方式。
想实现发送邮件需经过以下几步:
1. 登录 邮件服务器
2,构造符合邮件协议规则要求的邮件内容(email模块)
3,发送Python对SMTP支持有smtplib和email两个模块, email负责构造邮件, smtplib负责发送邮件,它对smtp协议进行了简单的封装。。
2.7.1 发送⼀封最简单的信语法如下:
import smtplib from email.mime.text import MIMEText # 邮件正⽂文 from email.header import Header # 邮件头 # 登录邮件服务器器 smtp_obj = smtplib.SMTP_SSL("smtp.exmail.qq.com", 465) # 发件人邮箱中的SMTP服务 器器,端⼝口是25 smtp_obj.login("nami@luffycity.com", "xxxx-sd#gf") # 括号中对应的是发件人邮箱账 号、邮箱密码 #smtp_obj.set_debuglevel(1) # 显示调试信息 # 设置邮件头信息 msg = MIMEText("Hello, ⼩小哥哥,约么?800上门,新到学⽣生妹...", "plain", "utf-8") msg["From"] = Header("来⾃自娜美的问候","utf-8") # 发送者 msg["To"] = Header("有缘⼈人","utf-8") # 接收者 msg["Subject"] = Header("娜美的信","utf-8") # 主题 # 发送 smtp_obj.sendmail("nami@luffycity.com", ["alex@luffycity.com", "317822232@qq.com"], msg.as_string())
2.7.2 发送HTML格式的邮件
只需要改⼀下MIMEText() 第2个参数为html 就可以
# 设置邮件头信息 mail_body = ''' <h5>hello,⼩哥哥</h5> <p> 小哥哥,约么?800,新到学⽣妹.. <a href="http://wx1.sinaimg.cn/mw1024/5ff6135fgy1gdnghz2vbsg205k09ob2d.gif">这是我 的照⽚片</a></p> </p> ''' msg = MIMEText(mail_body, "html", "utf-8")
2.7.3 在HTML文本中插入图片
# -*- coding:utf-8 -*- # created by Alex Li - 路⻜飞学城 import smtplib from email.mime.image import MIMEImage from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.header import Header # 登录邮件服务器器 smtp_obj = smtplib.SMTP_SSL("smtp.exmail.qq.com", 465) # 发件⼈人邮箱中的SMTP服务 器器,端⼝口是25 smtp_obj.login("nami@luffycity.com", "333dsfsf#$#") # 括号中对应的是发件⼈人邮箱账 号、邮箱密码 smtp_obj.set_debuglevel(1) # 显示调试信息 # 设置邮件头信息 mail_body = ''' <h5>hello,⼩小哥哥</h5> <p> ⼩小哥哥,约么?800,新到学⽣生妹.. <p><img src="cid:image1"></p> </p> ''' msg_root = MIMEMultipart('related') # 允许添加附件、图⽚片等 msg_root["From"] = Header("来⾃自娜美的问候","utf-8") # 发送者 msg_root["To"] = Header("有缘⼈人","utf-8") # 接收者 msg_root["Subject"] = Header("娜美的信","utf-8") # 主题 # 允许添加图⽚片 msgAlternative = MIMEMultipart('alternative') msgAlternative.attach(MIMEText(mail_body, 'html', 'utf-8')) msg_root.attach(msgAlternative) # 把邮件正⽂文内容添加到msg_root⾥里里 # 加载图⽚片, fp = open('girl.jpg', 'rb') msgImage = MIMEImage(fp.read()) fp.close() # 定义图⽚片 ID,在 HTML ⽂文本中引⽤用 msgImage.add_header('Content-ID', '<image1>') msg_root.attach(msgImage) # 添加图⽚片到msg_root对象⾥里里 # 发送 smtp_obj.sendmail("nami@luffycity.com", ["alex@luffycity.com", "317828332@qq.com"], msg_root.as_string())
1.4什么是包(package)
若你写的项目较复杂,有很多代码文件的话,为了方便管理,可以用包来管理。 一个包其实就是一个文件目录,你可以把属于同一个业务线的代码文件都放在同一个包里。
包将有联系的模块组织在一起,即放到同一个文件夹下,并且在这个文件夹创建一个名字为_init_.py 文件,那么这个文件夹就称之为包。
如何创建⼀个包?
创建包的流程
[NeW一[Python Package]一输入包名一[OK灯一新建功能模块(有联系的模块)。 注意:新建包后,包内部会自动创建_init·py文件,这个文件控制着包的导入行为。
1.新建包mypackage 2.新建包内模块:my_module1和my_module2 3.模块内代码如下
只需要在目录下创建一个空的__init__。py 文件,这个目录就变成了包。这个文件叫包的初始化文件,一般为空,当然也可以写东西,当你调用这个包下及其任意子包的的任意模块时,这个_init_·py 文件都会先执行。以下有a、b2个包, a2是a的子包, b2是b的子包
day6 课件 a init_.py init_.py a_mod2.py a_module.pya2 b init.pY b2 init_.py b2_mod.py b_module.py
若在a_module.py模块里导入b2_mod.py的话,怎么办?
a_module.py的文件路径为/Users/alex/Documents/work/PyProjects/py8days_camp/day6/课件/a/a2/a_module.py
想导入成功,直接写以下代码就可以from day6.课件.b.b2 import b2_mod
导入包的方法
方法一
import包名.模块名 包名.模块名.目标
体验
import my_package.my_module1 my_package.my_module1.info_print1()
方法二
注意:必须在_init_.py文件中添加__all__=[],控制允许导入的模块列表。
from包名import 模块名.目标
from my_package import * my_module1.info_print1()
为何从day6开始?而不是从 py8days_camp 或课件 开始呢?
因为你的sys.path列表里,已经添加了相关的路径 ['/Users/alex/Documents/work/PyProjects/py8days_camp/day6/课件/a/a2'/'/Users/alex/Documents/work/PyProjects/py8days_camp', # <---就是这个。.'/Applications/PyCharm.app/Contents/helpers/pycharm_display''/Library/Frameworks/Python.framework/Versions/3.6/lib/python36.zip', '/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6',/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/lib-dynload','/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/sitepackages',"/Applications/PyCharm.app/Contents/helpers/pycharm_matplotlib_backend']
手动添加sys.path路径
你会说,我没有添加这个,/Users/alex/Documents/work/PyProjects/py8days-camp'呀,它是怎么进到 sys.path 里的?
答案是Pycharm自动帮你添加的,若你脱离pycharm再执行这个a_module.py就会报错了。
Alexs-MacBook-Pro:a2 alexs python3 a_module.py Traceback (most recent call last):File "a_module.py", line 7, in <module>from day6.课件.b.b2 import b2_modModuleNotFoundError: No module named 'day6'不用慌, 自己手动添加sys.path路径就可以
import os import sys base_dir=os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.pa th.dirname(os.path.abspath(__file__)))))) # 取到路 径/Users/alex/Documents/work/PyProjects/py8days_camp print(base_dir) sys.path.append(base_dir) # 添加到sys.path⾥ from day6.课件.b.b2 import b2_mod
学员管理系统开发(综合应用)
系统需求
使用面向对象编程思想完成学员管理系统的开发,具体如下:
系统要求:学员数据存储在文件中
系统功能:添加学员、删除学员、修改学员信息、查询学员信息、显示所有学员信息、保存学员信息及退出系统等功能。
准备程序文件
分析
角色分析
学员
管理系统
工作中的注意事项
1.为了方便维护代码,一般一个角色一个程序文件
2.项目要有主程序入口,习惯为main.py
创建程序文件
创建项目目录
例如:StudentManagerSystem
程序文件如下:
程序入口文件:main.py
学员文件:student.py
管理系统文件:managerSystem.py
书写程序
student.py
需求
学员信息包含:姓名、性别、手机号;
添加str_魔法方法,方便查看学员对象信息
代码
class Student(object): definit(self,name,gender,tel): self.namename self.gender gender self.tel tel def _str_(self): return f"您的姓名是{self.name,年龄{self.gender},性别{se1f.tel}" # 测试:stu=Student("aa","f","12") # print(stu)
managerSystem.py
需求:
存储数据的位置:文件(student..data)
加载文件数据
修改数据后保存到文件
存储数据的形式:列表存储学员对象
系统功能
添加学员
删除学员
修改学员
查询学员信息
显示所有学员信息
保存学员信息
代码实现
定义类
class StudentManager(object): definit_(self): #存储数据所用的列表 self.student_list [
管理系统框架
需求:系统功能循环使用,用户输入不同的功能序号执行不同的功能。
步骤
定义程序入口函数
加载数据
显示功能菜单
用户输入功能序号
根据用户输入的功能序号执行不同的功能
定义系统功能函数,添加、删除学员等
代码
class StudentManager(object): def __init__(self): # 存储数据所用的列表 self.student_list = [] # 一, 程序入口函数,启动程序后执行的函数 def run(self): # 1. 加载学员信息 self.load_student() while True: # 2. 显示功能菜单 self.show_menu() # 3. 用户输入功能序号 menu_num = int(input("请输入您需要的功能序号:")) # 4. 根据用户输入的功能序号执行不同的功能 if menu_num == 1: # 添加学员 self.add_student() elif menu_num == 2: # 删除学员 self.del_student() elif menu_num == 3: # 修改学员信息 self.modify_student() elif menu_num == 4: # 查询学员信息 self.search_student() elif menu_num == 5: # 显示所有学员信息 self.show_student() elif menu_num == 6: # 保存学员信息 self.save_student() elif menu_num == 7: # 退出系统 print("退出系统") break else: print("输入序号错误,为了您的资金安全,界面关闭") break
# 二,系统功能函 # 2.1显示功能菜单-·打印序号的功能对应关系-·静态 @staticmethod def show_menu(): print("请选择如下功能:") print("1:添加学员") print("2:删除学员") print("3:修改学员信息") print("4:查询学员信息") print("5:显示所以学员信息") print("6:保存学员信息") print("7:退出系统") # 2.2添加学员 def add_student(self): print("添加学员") # 2.3删除学员 def del_student(self): print("删除学员") # 2.4修改学员信息 def modify_student(self): print("修改学员") # 2.5查询学员信息 def search_student(self): print("查询学员信息") # 2.6显示所有学员信息 def show_student(self): print("显示所有学员信息") # 2.7保存学员信息 def save_student(self): print("保存学员信息") # 2.8加载学员信息 def load_student(self): print("加载学员信息")
main.py
# 1. 导入managerSystem模块 from managerSystem import * # 2. 启动学员管理系统 # 保证是当前文件运行才启动管理系统:if --创建对象并调用run方法 if __name__ == "__main__": student_manager = StudentManager() student_manager.run()
定义系统功能函数
添加学员
需求:用户输入学员姓名、性别、手机号,将学员添加到系统。
步骤
用户输入姓名、性别、手机号
创建该学员对象
将该学员对象添加到列表
代码
添加学员函数内部需要创建学员对象,故先导入student模块
from student import *
# 2.2添加学员 def add_student(self): # 1.用户输入姓名,性别,手机号 name = input("请输入您的姓名:") gender = input("请输入您的性别:") tel = input("请输入您的手机号:") # 2.创建学员对象 -- 类?类在student文件,先导入student模块,再创建对象 student = Student(name, gender, tel) # 3.将该对象添加到学员列表 self.student_list.append(student) print(self.student_list) print(student)
删除学员
需求:用户输入目标学员姓名,如果学员存在则删除该学员。
步骤
用户输入目标学员姓名
遍历学员数据列表,如果用户输入的学员姓名存在则删除,否则则提示该学员不存在。
代码
# 2.3删除学员 def del_student(self): # 1. 用户输入目标学员姓名 del_name = input("请您输入您要删除的学员姓名:") # 2. 如果用户输入的目标学员存在则删除,否则提示学员不存在 for i in self.student_list: if i.name == del_name: # 删除该学员对象 self.student_list.remove(i) break else: print("查无此人") # 打印学员列表,验证删除功能 print(self.student_list)
修改学员信息
需求:用户输入目标学员姓名,如果学员存在则修改该学员信息。
步骤
用户输入目标学员姓名;
遍历学员数据列表,如果用户输入的学员姓名存在则修改学员的姓名、性别、手机号数据,否则则提示该学员不存在。
代码
# 2.4修改学员信息 def modify_student(self): # 1. 用户输入目标学员姓名 modify_name = input("请您输入您要修改的学员姓名:") # 2. 如果用户输入的目标学员存在则修改姓名,性别,手机号等数据,否则提示不存在 for i in self.student_list: if i.name == modify_name: i.name = input("请输入学员姓名:") i.gender = input("请输入学员性别:") i.tel = input("请输入学员手机号:") print(f"修改该学员信息成功,姓名{i.name},性别{i.gender},手机号{i.tel}") break else: print("查无此人")
查询学员信息
需求:用户输入目标学员姓名,如果学员存在则打印该学员信息
步骤
用户输入目标学员姓名
遍历学员数据列表,如果用户输入的学员姓名存在则打印学员信息,否则提示该学员不存在
代码
# 2.5查询学员信息 def search_student(self): # 1. 用户输入学员姓名 search_name = input("请输入您要查询的学员姓名:") # 2. 如果用户输入的目标学员存在,则打印学员信息,否则提示学员不存在 for i in self.student_list: if i.name == search_name: print(f"您查询的姓名是{i.name},性别{i.gender},手机号{i.tel}") break else: print("查无此人")
显示所有学员信息
打印所有学员信息
步骤
遍历学员数据列表,打印所有学员信息
代码
#2.6显示所有学员信息 def show_student(self): print("姓名\t性别t手机号") for i in self.student list: print(f"姓名:[i.name}t,性别:{i.gender}\t,手机号码:[i.tel}")
保存学员信息
需求:将修改后的学员数据保存到存储数据的文件。
步骤
打开文件
文件写入数据
关闭文件
思考
1,文件写入的数据是学员对象的内存地址吗?
2.文件内数据要求的数据类型是什么?
拓展__dict__
收集类对象和属性对象的值,返回一个字典
#1.定义类 class A(object): a =0 definit_(self): self.b 1 #2.创建对象 aa =A() #3.调用dict print(A.__dict__) print(aa._dict_)
代码
# 2.7保存学员信息 def save_student(self): # 1. 打开文件 f = open("student.data", "w") # 2.文件写入学员数据 # 注意1:文件写入的数据不能是学员对象的内存地址,需要把学员数据转换成列表字典数据再存储 new_list = [i.__dict__ for i in self.student_list] # [{"name":"aa", "gender":"nv", "tel": "111"}] print(new_list) # 注意2:文件内数据要求为字符串类型,故需要先转换数据类型为字符串才能文件写入数据 f.write(str(new_list)) # 3.关闭文件 f.close
加载学员信息
需求:每次进入系统后,修改的数据是文件里面的数据
步骤
尝试以"r"模式打开学员数据文件,如果文件不存在则以"w"模式打开文件
如果文件存在则读取数据并存储数据
■读取数据
■转换数据类型为列表并转换列表内的字典为对象
■存储学员数据到学员列表
关闭文件
代码
# 2.8加载学员信息 def load_student(self): # 尝试以"r"模式打开学员数据文件,如果文件不存在则以"w"模式打开文件 try: f = open("student.data", "r") # 如果文件存在则读取数据并存储数据 except: f = open("student.data", "w") else: # ■读取数据 data = f.read() # ■转换数据类型为列表并转换列表内的字典为对象,存储学员数据到学员列表 new_list = eval(data) self.student_list = [Student(i["name"], i["gender"], i["tel"]) for i in new_list] finally: # 关闭文件 f.close()