单例模式与pickle模式

单例模式实现的多种方式

1.使用动静态方法
    class C1:
        __instance = None

        def __init__(self, name, age):
        self.name = name
        self.age = age

        # 被@classmethod修饰的函数,默认绑定给类,类调用时第一个参数就是类本身,对象调用时会将产生该对象的类当做第一个参数传进去
        @classmethod  
        def singleton(cls):
            if not cls.__instance:
                cls.__instance = cls('jason', 18)  # 创建一个对象与__instance绑定
            return cls.__instance  # 返回__instance
    obj1 = C1.singleton()
    obj2 = C1.singleton()
    print(id(obj1), id(obj2))  # 打印出来的obj1与obj2的内存地址相同,obj1与obj2都是通过singleton方法接受的__instance,所以内存地址相同
    obj3 = C1('kevin', 20)
    print(id(obj3))  # 此时是通过__init__产生了一个新的对象

2.通过元类
class Mymeta(type):
    def __init__(self, name, bases, dic):  # 定义类Mysql时就触发
        # 事先先从配置文件中取配置来造一个Mysql的实例出来
        self.__instance = object.__new__(self)  # 产生对象
        self.__init__(self.__instance, 'jason', 18)  # 初始化对象
        # 上述两步可以合成下面一步
        # self.__instance=super().__call__(*args,**kwargs)
        super().__init__(name, bases, dic)

    def __call__(self, *args, **kwargs):  # Mysql(...)时触发
        if args or kwargs:  # args或kwargs内有值
            obj = object.__new__(self)
            self.__init__(obj, *args, **kwargs)
            return obj
        return self.__instance


class Mysql(metaclass=Mymeta):
    def __init__(self, name, age):
        self.name = name
        self.age = age
通过元类定义出来的单例模式使用方法与动静态方法定义出来的单例模式的使用方法一致,在不传值的时候,创建的对象都是相同的,一旦传值创建出来的对象就是独有的

3.基于模块的单例模式
    提前产生一个对象,后续通过模块导入使用
    class C1:
        def __init__(self, name):
        self.name = name

    obj = C1('jason')
    定义好的对象,其他模块在导入使用的时候是这个对象本身

4.通过装饰器定义出来的单例模式
def outer(cls):
    _instance = cls('jason', 18)  # 先创建一个固定的对象
    def inner(*args, **kwargs):
        if args or kwargs:  # 判断args或kwargs内是否有值
            obj = cls(*args, **kwargs)  # 创建一个新的对象
            return obj 
        return _instance

    return inner


@outer  # Mysql=outer(Mysql) 将类名作为参数传入outer中
class Mysql:
    def __init__(self, host, port):
        self.host = host
        self.port = port
    
在不传值的时候,创建的对象都是相同的,一旦传值创建出来的对象就是独有的

pickle序列化模块

pickle模块的作用json模块相同都是序列化数据,但两者还是由本质上的区别的
pickle模块可以序列化python中所有的数据类型但是只能在python中使用,无法跨语言,而且序列化到文件中时使用二进制模式
eg:
    产生一个对象并将对象保存到文件中,取出来后 还是一个对象
    class C1:
        def __init__(self, name, age):
            self.name = name
            self.age = age

        def func1(self):
            print('from func1')

       def func2(self):
            print('from func2')

    obj = C1('jason', 18)
    import pickle
    with open(r'a.txt', 'wb') as f:
        pickle.dump(obj, f)
    with open(r'a.txt', 'rb') as f:
        a = pickle.load(f)
    a.func1()  # from func1
    a.func2()  # from func2
posted on 2023-04-05 17:27  zyg111  阅读(36)  评论(0)    收藏  举报