面向对象

  • 题目讲解

  • 设计模式之单例模式

  • 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模块保存对象只是存了一些名称空间的关系,只要类在程序运行的时候还在,名称空间还在,那么这个对象就保存到文件中去,取出来后还可以当对象使用。