第一时间关注 Python 技术干货!
阅读文本大概需要 5 分钟。
前言
在我们的真实世界之外,网络世界也是异常的紧张和繁忙,他们各司其职。最忙的当属 CPU 了,每天 24 小时都在工作,真的是整天神龙见首不见尾。
大家都在这紧张的节奏中工作着。有一天,小 c 加班到很晚,背着电脑包在路上走着。忽然发现了之前见过的小 d,他追上去拍了一下小 d 的肩膀说,嘿,小 d,你也刚下班呀?小 d 满脸的黑人问号,你是谁呀?
小 c 说你不认识我了?我们都是 Python 爸爸大家族里一个 Animal 类实例化出来的对象呀。我是 cat 对象,你是 dog 对象,当时Animal类创造我们的时候,我还拍照了呢。我给你看看照片。
内存地址
小 d 好像有点印象了。小 c 接着问他,你现在回家吗?你还记得你家的地址吗?小 d 说,我从来不去记自己家里的地址的,我只按照固定的路线走就行。小 c 解释说,你可以用 Python 家族提供的方法来查一下自己家的地址呀,这个方法我们每个人都可以用,小 c 边说着边从背包里拿出一个小盒子,这就是 id 盒,你把指纹放在中间就可以显示你家的地址了。
这时 id 盒屏幕上显示了小 c 和小 d 家的地址。
小 d 惊呼道,哇,很神奇耶,这个 id() 方法很强大耶,接着,小 c 指着盒子的背面的文字给小 d 看,这是 id() 方法的说明书。
小 d 恍然大悟,原来这个 id() 函数用于获取对象的内存地址。
小 d 继续不解的问,我们不是同一个类的实例化出来的对象吗?为什么我们的内存地址会不一样呢?我们的地址可以生成一样的吗?
单例模式
小 c 说道,我们可以创建单例模式,这样的话我们的地址就是一样的了。什么是单例模式呢?我们应该怎么创建呢?他们两个边走边说。转眼间,他们就走到了 Hello World 咖啡馆。小 c 说,我们边喝咖啡边聊吧。
小 c 和 小 d 点了两杯卡布基诺,小 c 说到,单例模式是保证一个类仅有一个实例,并提供一个访问它的全局访问点。
Python 中,一个类创建对象实例是通过调用父类 object 的 __new__(cls) 方法来创建对象的。我们可以通过重写 __new(cls) 方法去实现类只创建一个实例。
小 c 喝了一口咖啡,继续解释道,我们先把类属性初始化为 None,每次都对类属性做判断,如果类属性为 None,表示第一次创建,我们通过父类的__new__(cls)来创建实例。如果类属性不为 None,表示之前已经创建过了,直接返回上一个对象的实例就行。这样,通过上面的单例模式,我们的内存地址就是一样的啦。
小 d 惊呼道:哇,好神奇啊。
但是,我还有个问题,单例模式有什么好处呢?
单例模式作用
小 c 说,单例模式有自己的优缺点。
优点
1、实例控制
单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。
2、灵活性
因为类控制了实例化过程,所以类可以灵活更改实例化过程。
缺点
1、开销
虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。
2、可能的开发混淆
使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用 new 关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
3、对象生成期
不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于 .NET Framework 的语言),只有单例类能够导致单例类中出现悬浮引用。
所以,我们需要根据自己的需求,是否选择使用单例模式来解决问题。
通过小 c 的讲解,小 d 终于明白了,他们一起走出Hello World 咖啡馆,消失在灯火阑珊的夜色中。
领取专属 10元无门槛券
私享最新 技术干货