Python中, 仿照经典代码实现单例, 却出现了不是单例的的状态, 代码哪里出错了 ?

 manassatromble 发布于 2022-10-26 19:14
实际现象
  • 期望实现单例, 保持某个属性全局唯一

预期现象
  • 仿照经典实现代码, 却出现了不是单例的情况

我要做什么
  • 实现scheduler全局唯一, 不派生过多的scheduler

重现步骤
  1. 拷贝代码

  2. 运行之

  3. 查看内存地址

相关代码
  • 仿照经典实现

from apscheduler.schedulers.background import BackgroundScheduler

class Borg(object):
    

    __shared_state = {}

    def __init__(self):
        self.__dict__ = Borg.__shared_state

        self.scheduler = BackgroundScheduler()
        
        
s1 = Borg().scheduler
s2 = Borg().scheduler

print s1, s2


#  
# 
  • 我自己想的办法

from apscheduler.schedulers.background import BackgroundScheduler


class Borg(object):
    @classmethod
    def get_scheduler(cls):
        try:
            cls_scheduler = cls.scheduler
        except AttributeError as e:
            cls.scheduler = BackgroundScheduler()

            return cls.scheduler
        else:
            return cls_scheduler
        




bs1 = Borg.get_scheduler()
bs2 = Borg.get_scheduler()
bs3 = Borg.get_scheduler()
print bs1, bs2, bs3


#  
#  
# 
上下文环境
  • 产品版本: Python 2.7 APScheduler最新

  • 操作系统: Linux

  • Github链接, 经典实现: https://github.com/faif/pytho...

1 个回答
  • 经典例子这个不能算是纯单例,而是具有单例特性的Brog模式。

    其魔法在于利用类Brog共享的类属性__shared_state的字典,后面创建的实例会覆盖前面实例的__dict__

    s1 = Borg().scheduler
    s2 = Borg().scheduler

    创建一个实例s1,同时初始化属性scheduler,此时的地址是0x02623DF0,再创建一个实例s2,然后修改了属性scheduler,地址为0x02D801D0s1s2其实是两个不同实例,只不过他们的属性共用类属性,看起来就像单例的效果。

    如果把代码改成这样,应该就能看得更清楚过程:

    s1 = Borg()
    print(s1.scheduler)
    s2 = Borg()
    print(s1.scheduler)
    print(s2.scheduler)
    print(s1.scheduler is s2.scheduler)
    2022-10-27 01:22 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有