面向对象
-
题目讲解
-
设计模式之单例模式
-
pickle模块
题目讲解
编写元类规定对象的所有数据值转大写
obj.name = 'jason'
obj.gender = 'male'
print(obj.name)
print(obj.gender)
结果如下:
class MyTypeClass(type):
def __call__(self, *args, **kwargs): # *args接收类括号里的参数
args = [i.upper() for i in args] # 采用for循环,把循环里的'i'全部改为大写
return super().__call__(*args, **kwargs) # 再次调用父类的双下call
class MyClass(metaclass=MyTypeClass):
def __init__(self, name, gender):
self.name = name
self.gender = gender
obj = MyClass('jason', 'male')
print(obj.name) # JASON
print(obj.gender) # MALE
对象在实例化的时候需要使用元类里的双下call方法,因为是类加括号,所有自动调用元类里的双下call,不会执行双下init,然后类(MyClass)加括号里面的参数会被*args接收,再次调用父类的双下call,再将两个参数传入进去,下面的双下init就可以拿到数据然后重新给args赋值,最后再使用for循环方法,将for循环里的i全部改成大写就可以了。
单例模式
在IT行业中设计模式总共有23种,可以分为三大类:1.创建型、2.结果型、3.行为型
# 设计模式之单例模式:
单例模式的意思是一个类只能产生一个对象,可以节约资源,因为类只要加括号实例化,产生的对象肯定不一样。
# 应用场景:如果一个类中有很多非常牛逼的绑定给对象的方法,我们在很多的地方需要使用它,那么不同的程序员来用,不知道里面有没有产生对象,都会去创建一个新对象,如此往复的话就会造成资源浪费。
# 如何实现:我们需要在类实例化对象的时候进行干涉(元类可以提供一种高度定制类和对象的创建过程)
单例模式:
class Single(type): # 先定义一个单例元类
new_obj = None # 定义一个全局变量
def __call__(self, *args, **kwargs): # 类加括号自动触发双下call方法
if not self.new_obj: # 反向判断里面没有值
obj = super().__call__(*args, **kwargs) # 产生一个对象
self.new_obj = obj # 给对象赋值一个独有的属性
return self.new_obj # 返回self,new_obj
return self.new_obj # 返回self,new_obj
class MyClass(metaclass=Single):
def __init__(self, name):
self.name = name
obj1 = MyClass('jason')
obj2 = MyClass('tony')
print(id(obj1), id(obj2))
print(obj1.__dict__,obj2.__dict__) # {'name':'jason'} {'name':'jason'}
先定义一个单例元类,因为类加括号会自动触发元类里的双下call,然后在元类里定义一个变量先存着,就是用来判断一下元类里面是否已经调用过一次双下call,如果已经产生过一次对象就不再产生。两个结果是一样是因为第一次使用双下call的时候对象已经在名称空间产生了一个值,但是第二次的时候,对象没有产生自己的名称空间里的值,所以还是拿的第一次名称空间里的值。
pickle模块
该模块只支持python,兼容性很差
# 需求:将对象保存到文件,并且取出来之后还可以使用对象的功能
import 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) # MyClass的一个对象
print(data.name) # jason
print(data.school) # school
不能直接使用json方法,json方法只能序列化一些基本数据类型,而对象根本就不是数据类型,不能修改源码,所以使用pickle模块,使用pickle模块将对象保存到文件中,文件里是一个二进制模式,然后使用pickle模块取出的话要确保类还存在,因为它需要一个名称空间去找名字,从文件里面读出来的是MyClass的一个对象。pickle模块保存对象只是存了一些名称空间的关系,只要类在程序运行的时候还在,名称空间还在,那么这个对象就保存到文件中去,取出来后还可以当对象使用。