一、内容
- 1.1、单例设计模式
- 1.2、
__new__
方法 - 1.3、Python 中的单例
二、单例设计模式
-
2.1、设计模式
- 设计模式 是 前人工作的总结和提炼,通常,被人们广泛流传的设计模式都是针对 某一特定问题 的成熟的解决方案
- 使用 设计模式 是为了可重用代码、让代码更容易被他人理解、保证代码可靠性
-
2.2、单例设计模式
-
目的
—— 让 类 创建的对象,在系统中 只有 唯一的一个实例 - 每一次执行 类名() 返回的对象,内存地址是相同的
-
-
2.3、单例设计模式的应用场景
音乐播放 对象,回收站 对象,打印机 对象
三、__new__
方法
3.1、使用 类名() 创建对象时,Python 的解释器 首先 会 调用
__new__
方法为对象 分配空间,如果是 类对象的调用是不是走__new__
方法的-
3.2、
__new__
是一个 由 object 基类提供的 内置的静态方法,主要作用有两个:- (1) 在内存中为对象 分配空间
- (2)
返回
对象的引用
3.3、Python 的解释器获得对象的 引用 后,将引用作为 第一个参数,传递给
__init__
方法-
3.4、重写
__new__
方法 的注意事项- 重写
__new__
方法 一定要 return super().new(cls) - 否则 Python 的解释器 得不到 分配了空间的 对象引用,就不会调用对象的初始化方法
- 注意:
__new__
是一个静态方法,在调用时需要 主动传递cls
参数
- 重写
-
3.5、如下代码(使用 类名() 创建对象时,Python 的解释器 首先 会 调用 new 方法为对象 分配空间)
class MusicPlayer(object): def __new__(cls, *args, **kwargs): # 1、创建对象时候,__new__方法会被自动调用 # 2、如果不返回任何结果,下面的__init__初始化方法是不会走的。 # 3、必须在返回传 cls return super().__new__(cls) def __init__(self): print("初始化音乐播放对象") player = MusicPlayer() print(player)
上述代码中的def __new__
里面如果不写return
,下面的__init__
是不会走的
四、Python 中的单例
4.1、单例 —— 让 类 创建的对象,在系统中 只有 唯一的一个实例,也就是不管利用
类名()
创建多少个实例对象,其内存地址都是一样的-
4.2、既然内存地址是一样的,那么我们就要想到
__new__
方法,它是初始化内存地址的方法,我们只需要在这里进行每次返回同一个内存地址即可,具体的实现如下:- 定义一个 类属性
,初始值是None
,用于记录 单例对象的引用 - 重写
__new__
方法 - 如果
类属性 is None
(is是用来判断内存地址是不是一样,=
是用来判断数据是不是一样),调用父类方法分配空间,并在类属性中记录结果 - 返回 类属性 中记录的 对象引用
- 定义一个 类属性
-
4.3、单利代码示例
class Person(object): # 定义类属性记录单例对象引用 instance = None def __new__(cls, *args, **kwargs): # 1. 判断类属性是否已经被赋值 if cls.instance is None: cls.instance = super().__new__(cls) # 2. 返回类属性的单例引用 return cls.instance person1 = Person() print(person1) person2 = Person() print(person2) 打印结果是: <__main__.Person object at 0x1016c2160> <__main__.Person object at 0x1016c2160> 我们可以看到上述的代码打印的 **内存地址是一样的**
-
4.4、如何让
__init__
代码也只初始化一次 ?我们可以模仿单利的设计模式,也定义一个 类属性 来记录是否进行过初始化,代码如下:class Person(object): # 定义类属性记录是否进行过初始化 init_flag = False def __init__(self): # 1、判断类属性是否已经被赋值(也就是是否进行过初始化,进行过返回) if Person.init_flag: return # 2、进行初始化操作 print("进行初始化操作") # 3、修改init_flag的值(代表进行过初始化操作) Person.init_flag = True person1 = Person() person2 = Person() 打印结果是: 进行初始化操作
通过上面可以看出来只初始化了一次