15.单例模式
单例模式(Singleton Pattern),这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
- python中的单例
python类实例化执行原理分析
- 首先在我们调用构造方法时会自动去调用类的 __init__ 方法, __init__ 方法会去调用一个叫 __new__ 的方法,__new__ 会返回一个对象实例,这个实例就是类的实例
class Person:
_instance = None
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
person1 = Person()
person2 = Person()
print(id(person1))
print(id(person2))
class Person:
_instance = None
def __init__(self, name, age):
self.name = name
self.age = age
def __new__(cls, *args, **kwargs):
if not cls._instance:
cls._instance = super().__new__(cls)
return cls._instance
person1 = Person("孙悟空", 726)
person2 = Person("假猴子", 726)
print(id(person1))
print(id(person2))
print(person1.name)
print(person2.name)
- 当一个实例被创建,它的属性就应该定下来了,而不是继续改变
class Person:
_instance = None
name = None
age = None
def __init__(self, name, age):
self.__new__(self, name, age)
def __new__(cls, name, age):
if not cls._instance:
cls.name = name
cls.age = age
cls._instance = super().__new__(cls)
return cls._instance
person1 = Person("孙悟空", 726)
person2 = Person("假猴子", 726)
print(id(person1))
print(id(person2))
print(person1.name)
print(person2.name)
实现方式二:元类 metaclass
- 当一个类设置了元类以后,创建对象是通过调用元类中的
__call__()
函数实现。
class SingletonMetaClass(type):
_instance = None
def __call__(self, *args, **kwargs):
if self._instance:
self._instance = super().__call__(*args, **kwargs)
return self._instance
class Singleton(metaclass=SingletonMetaClass):
pass
# 示例:
a = Singleton()
b = Singleton()
print(id(a) == id(b))
- 方法走向解析:
class SigletonMetaClass(type):
_instance = None
def __new__(cls, *args, **kwargs):
print("SigletonMetaClass=>new")
return super().__new__(cls, *args, **kwargs) # 断点1
def __call__(self, *args, **kwargs):
print("SigletonMetaClass=>call")
if self._instance is None:
self._instance = super().__call__(*args, **kwargs)
return self._instance # 断点2
class Singleton(metaclass=SigletonMetaClass):
def __new__(cls, *args, **kwargs):
print("Singleton=>new")
return super().__new__(cls) # 断点3
s1 = Singleton()
print("="*20)
s2 = Singleton()
print(id(s1) == id(s2))
"""
SigletonMetaClass=>new
SigletonMetaClass=>call
Singleton=>new
====================
SigletonMetaClass=>call
True
"""
精简版(用实例名覆盖类名后,执行 Singleton()
就是在调用 __call__()
函数,总是返回自身。)
class Singleton:
def __call__(self):
return self
@property
def name(self):
return self._name
@name.setter
def name(self, name):
self._name = name
Singleton = Singleton()
# 示例:
a = Singleton()
b = Singleton()
print(id(a) == id(b))
a.name = "孙悟空"
print(b.name)