需求:编写元类规定对象的所有数据值转大写
eg:
obj.name = 'jason'
print(obj.name) # JASON
分析:我们的需求是对象的数据值转大写,因此需要干涉元类的数据产生,我们知道双下init之前运行的是元类的双下call,因此我们可以在添加数据之前在元类多做一步操作,将传入的数据转为大写
class MyTypeClass(type): def __call__(self, *args, **kwargs): args = [i.upper() for i in args] # for循环元组args然后转大写再赋值给args return super().__call__(*args, **kwargs) class MyClass(metaclass=MyTypeClass): def __init__(self, name, gender): self.name = name self.gender = gender def __setattr__(self, key, value): self.__dict__[key] = value.upper() obj = MyClass('jason', 'male') print(obj.name) # JAOSON print(obj.gender) # MALE obj.hobby = 'jdb' print(obj.hobby) # JAB
设计模式:是前辈们发明的经过反复验证用于解决固定问题的固定套路
在IT行业中设计模式总共有23种,可以分为三大类
单例模式:是指一个类只能产生一个对象,用于节省资源
应用场景:有一个类中有很多非常厉害的绑定给对象的方法,需要在很多地方使用,不同人来用不知道有没有产生对象,所以自己会创建一个新对象,如此往复会造成资源的浪费,因此单例模式应运而生
如何实现:在类实例化对象的时候干涉>>>元类
注意:单例模式有很多编写方式,这里展示一种:
class Single(type): new_obj = None # 设置一个标志,产生过对象则该改变 def __call__(self,*args,**kwargs): if not self.new_obj: # 判断标志不为空时 obj = super().__call__(*args,**kwargs) # 获取双下call的返回值 self.new_obj = obj # 将返回值赋值给new_obj,便于下面获取已经获取过一次的对象值 return self.new_obj return self.new_obj # 已经产生对象,使用产生过的一个对象 class MyClass(metaclass=Single): def __init__(self,name): self.name = name obj1 = MyClass('jason') obj2 = MyClass('tony') print(obj1.__dict__,obj2.__dict__) # {'name':'jason'} {'name':'jason'}
单例的实现方式不固定,还有很多种,可以访问下面网站了解:
https://www.cnblogs.com/Dominic-Ji/p/10525994.html
学习该模块的目的仅仅是为了子啊选课系统中使用,后期会学习ORM就不会用pickle了,因为该模块只支持python,兼容性很差!
那么问题来了,pickle模块有哪些用处呢?看下面需求,举个例子
需求:将对象保存到文件 并且取出来之后还可以使用对象的功能
分析:从我们目前学习的内容来看,基本上没有能将对象存入文件还能保证对象的名称空间内容不丢失的,因此,需要用到pickle模块
import pickle # 调用pickle模块 class MyClass(object): # 定义一个简单的类 school = 'school' def __init__(self, name): self.name = name def choose_course(self): print('%s正在选课'%self.name) obj = MyClass('jason') # 产生一个对象 print(obj.school) obj.choose_course() with open(r'%s'%obj.name,'wb') as f: # 存入文件 pickle.dump(obj, f) with open(r'jason','rb') as f: # 获取文件内容 data = pickle.load(f) print(data) # {'name':'jason'} print(data.name) # jason 特别注意:pickle产生的文件只有在原来产生对象的类存在时才能正常使用,因此一般获取到的pickle对象保存的数据都是在代码运行时临时存在的,如果没有原来的代码,那么光有这个文件是使用不了里面的对象的
目的:练习面向对象编程
项目需求:
选课系统 角色:学校、学员、课程、讲师 要求: 1. 创建北京、上海 2 所学校 2. 创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海开 3. 课程包含,周期,价格,通过学校创建课程 4. 通过学校创建班级, 班级关联课程、讲师 5. 创建学员时,选择学校,关联班级 5. 创建讲师角色时要关联学校, 6. 提供三个角色接口 6.1 学员视图, 可以登录,注册, 选择学校,选择课程,查看成绩 6.2 讲师视图, 讲师登录,选择学校,选择课程, 查看课程下学员列表 , 修改所管理的学员的成绩 6.3 管理视图,登录,注册,创建讲师, 创建班级,创建课程,创建学校 7. 上面的操作产生的数据都通过pickle序列化保存到文件里
三层架构: 展示层:管理员视图、学生视图、讲师视图 后台核心程序:管理员功能、学生功能、讲师功能 数据层: models.by(存放所有角色的类)、 db_hanlter(用于存取数据)、 不同类型数据文件夹(管理员、讲师、学生)
为了减轻复杂度,班级直接等同于课程(不影响学习)
功能展示及架构关系:
# 管理员视图 >>> 管理员功能 注册 >>> 注册功能 >>> 存入管理员文件 登录 >>> 登录功能 >>> 获取管理员文件比对 创建学校 >>> 创建学习功能 创建课程 >>> 创建课程功能 创建讲师 >>> 创建讲师功能 # 讲师视图 >>> 讲师功能 登录 >>> 登录功能 >>> 管理员文件 查看教授课程 >>> 查看教授课程功能 选择教授课程 >>> 选择教授课程功能 查看课程学生 >>> 查看课程功能 评判学生分数 >>> 评判学生分数功能 # 学员视图 >>> 学员功能 注册 >>> 注册功能 >>> 存入管理员文件 登录 >>> 登录功能 >>> 获取管理员文件比对 选择学校 >>> 选择学校功能 选择课程 >>> 选择课程功能 查看分数 >>> 查看分数功能
start.py conf >>> settings.py core >>> src.py interface >>> admin_interface.py teach_interface.py student_interface.py db >>> models.py db_handlter.py admin >>> ...(管理员数据) teach >>> ...(讲师数据) student >>> ...(学生数据) log >>> scy.log(日志文件)
# src.py def run(): while True: # 初始界面 print(''' 1.管理员视图 2.讲师视图 3.学员视图 ''') ... def admin(): while True: # 管理员视图 print(''' 1.注册 2.登录 3.创建学校 4.创建课程 5.创建讲师 ''') ... def teach(): while True: # 讲师视图 print(''' 1.注册 2.登录 2.查看教授课程 3.选择教授课程 4.查看课程学生 5.评判学生分数 ''') ... def student(): while True: # 学员视图 print(''' 1.注册 2.登录 3.选择学校 4.选择课程 5.查看分数 ''') ... # admin_interface.py def run(): pass # teach_interface.py def run(): pass # student_interface.py def run(): pass # db,models.py class Admin: # 管理员对象 def __init__(self,name,pwd) self.name = name self.pwd = pwd ... class Teach: # 讲师对象 def __init__(self,name,pwd) self.name = name self.pwd = pwd ... class Student: # 学员对象 def __init__(self,name,pwd) self.name = name self.pwd = pwd ... # db,db_handlter def save(obj): # 存储对象 pass def select(name): # 获取存储的对象 pass
类产生的对象在保存的时候 自动创建一个与类名一样的文件夹名 将数据保存到该文件夹内 # 如何通过对象获取类对应的字符串名称 obj = Admin('jason',123) # 固定方法 print(obj.__class__) # <class '__main__.Admin'> 类名 print(obj.__class__.__name__) # Admin 字符串