单例实现方式

方式一、利用@classmethod类方法

  缺点:如果部调用方法属性,直接类的实例化,则不是单例

# 多次实例化得到的实例是指向同一个实例(对象)
IP = '1.1.1.1'
PORT = 3306


class MySQL:
    __instance = None
    
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port
    
    @classmethod
    def from_conf(cls):
        if cls.__instance is None:
            cls.__instance = cls(IP, PORT)
            return cls.__instance
        return cls.__instance


obj1 = MySQL.from_conf()
obj2 = MySQL.from_conf()


print(obj1)
print(obj2)
# <__main__.MySQL object at 0x00000000028F7B00>
# <__main__.MySQL object at 0x00000000028F7B00>

方法二、利用装饰器实现单例之完全单例

def singleton(cls):
    def warp(*args, **kwargs):
        if cls._instance is None:
            obj = cls(*args, **kwargs)
            return obj
        return cls._instance

    return warp


@singleton
class MySQL:
    _instance = None

    def __init__(self, ip, port):
        self.ip = ip
        self.port = port


print(MySQL('1.1.1.1', 3306))
print(MySQL('1.1.1.1', 3307))

# <__main__.MySQL object at 0x0000000001F87390>
# <__main__.MySQL object at 0x0000000001F87390>

方式二、利用装饰器实现单例之不传参数单例,传参不单例

IP = '1.1.1.1'
PORT = 3308


def singleton(cls):
    _instance = cls(IP, PORT)
    
    def warpper(*args, **kwargs):
        if args or kwargs:
            obj = cls(*args, **kwargs)
            return obj
        return _instance
    
    return warpper


@singleton
class MySQL:
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port


obj1 = MySQL()
obj2 = MySQL()
obj3 = MySQL('1.1.1.2',3309)
obj4 = MySQL('1.1.2.11',3310)
print(obj1)
print(obj2)
print(obj3)
print(obj4)
print(obj3.port)
print(obj4.port)

# <__main__.MySQL object at 0x00000000028C7B38>
# <__main__.MySQL object at 0x00000000028C7B38>
# <__main__.MySQL object at 0x00000000028C7BA8>
# <__main__.MySQL object at 0x00000000028C7C18>
# 3309
# 3310

 方法三、基于元类实现单例:

IP = '1.1.1.1'
PORT = 3309


class Myteta(type):
    def __init__(self, class_name, class_bases, class_dic):
        # 这里的self 其实就是MySQL
        instance = self(IP, PORT)
        self.__instance = instance
    
    def __call__(self, *args, **kwargs):
        # self = MySQL这个类
        if args or kwargs:
            obj = self.__new__(self)
            self.__init__(obj, *args, **kwargs)
            return obj
        return self.__instance


class MySQL(metaclass=Myteta):  # MySQL = Mymeta(....)
    def __init__(self, ip, port):
        self.ip = ip
        self.port = port


obj1 = MySQL()
obj2 = MySQL()
obj3 = MySQL()
obj4 = MySQL('1.1.1.10', 3317)
print(obj1)
print(obj2)
print(obj3)
print(obj4)

# <__main__.MySQL object at 0x00000000021D7BE0>
# <__main__.MySQL object at 0x00000000021D7BE0>
# <__main__.MySQL object at 0x00000000021D7BE0>
# <__main__.MySQL object at 0x00000000021D7C50>
原文地址:https://www.cnblogs.com/qianzhengkai/p/10808968.html