Python单例模式

__new__实现

关于__new__的内部原理,请点击

# 实例化一个jatrix
class Singleton(object):
    __instance = None
    __first_init = None

    def __new__(cls, age, name):
        if not cls.__instance:
            Singleton.__instance = object.__new__(cls)
        return cls.__instance

    def __init__(self, age, name):
        if not self.__first_init:
            self.age = age
            self.name = name
            Singleton.__first_init = True


a = Singleton(21, "jatrix")
b = Singleton(2, "jatrix")

print(id(a))
print(id(b))


print(a.age)
print(b.age)

a.age = 33
print(b.age)

# 输出
# 16500112
# 16500112
# 21
# 21
# 33

为了让子类不继承父类的__new方法,子类也应该调用object__new__方法

用装饰器实现单例模式

装饰器的实质就是对传进来的参数进行补充,使用装饰器可以装饰多个类

def singleton(cls, *args, **kwargs):
    instance = {}

    def __singleton():
        if cls not in instance:
            instance[cls] = cls
        return instance[cls]

    return __singleton


@singleton
class MyClass:
    kind = "type"

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


@singleton
class MyAnotherClass:
    name = "another"

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


one = MyClass()
two = MyClass()
print(id(one))
print(id(two))


another_one = MyAnotherClass()
another_two = MyAnotherClass()
print(id(another_one))
print(id(another_two))

使用元类实现

关于元类的详细知识,请点击

关于__call__方法的应用

class Singleton(type):
    def __init__(cls, name, bases, attrs):
        super(Singleton, cls).__init__(name, bases, attrs)
        cls._instance = None

    def __call__(cls, *args, **kwargs):
        if not cls._instance:
            cls._instance = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instance


class MyClass(metaclass=Singleton):
    pass


one = MyClass()
two = MyClass()
print(id(one))
print(id(two))

one.name = 1
print(two.name)

使用共享属性

共享属性表示每个实例有相同的属性,但是实例不相同

class Singelton(object):
    _state = {}

    def __new__(cls, *args, **kwargs):
        ob = super(Singelton, cls).__new__(cls)
        # 类维护所有实例的共享属性
        ob.__dict__ = cls._state
        return ob


class MyClass(Singelton):
    a = 1


one = MyClass()
two = MyClass()

print(two.a)
print(id(one))
print(id(two))
# 两个id不同 但是两者的__dict__的属性相同
print(id(one.__dict__))
print(id(two.__dict__))

推荐阅读更多精彩内容