python 单例模式

栏目: Python · 发布时间: 6年前

内容简介:python 实现单例方法有多种,下面我们介绍几种常用的方法。我们发现这样实现是有问题的,SubClass 无法创建自己的单例。 因为父类 SingleClass 的类对象数据会被所有子类共享,导致所有 SingleClass 子类无法创建新的对象。解决方法是我们在 SingleClass 类中使用字典保存每个子类的实例对象,改进后代码如下:

Python 单例实现方法

python 实现单例方法有多种,下面我们介绍几种常用的方法。

1. 使用元类实现单例

  • 创建一个 SingleInstance 的元类
  • 类指定 metaclass = SingleInstance
# 创建一个 metaclass 类
class SingleInstance(type):
    """
    类创建对象的时候会调用该方法, 返回类对象实例
    """
    def __call__(cls, *args, **kwargs):
        instance = getattr(cls, '__instance__', None)
        
        if instance is None:
            instance = super(SingleInstance, cls).__call__(*args, **kwargs)
            setattr(cls, '__instance__', instance)
            print("create instance ", instance)
        else:
            print("use old instance ", instance)
        print('got instance for ', cls)
        return instance


"""
测试方法:
1. 每次实验创建两个类,确认不同的类之间不会相互影响
2. 每个类创建两个对象,确认两个对象是一样的
"""
class TestClass0(metaclass=SingleInstance):
    def __init__(self):
        print("init test0 class object")


class TestClass1(metaclass=SingleInstance):
    def __init__(self):
        print("init test1 class object")
        

# 测试第一个类对象
test00 = TestClass0()
test01 = TestClass0()
print(test00, test01)

print('\n----------------------\n')

# 测试第二个类对象
test10 = TestClass1()
test11 = TestClass1()
print(test10, test11)
init test0 class object
create instance  <__main__.TestClass0 object at 0x7f5492fe66a0>
got instance for  <class '__main__.TestClass0'>
use old instance  <__main__.TestClass0 object at 0x7f5492fe66a0>
got instance for  <class '__main__.TestClass0'>
<__main__.TestClass0 object at 0x7f5492fe66a0> <__main__.TestClass0 object at 0x7f5492fe66a0>

----------------------

init test1 class object
create instance  <__main__.TestClass1 object at 0x7f5492fe69b0>
got instance for  <class '__main__.TestClass1'>
use old instance  <__main__.TestClass1 object at 0x7f5492fe69b0>
got instance for  <class '__main__.TestClass1'>
<__main__.TestClass1 object at 0x7f5492fe69b0> <__main__.TestClass1 object at 0x7f5492fe69b0>

2. 通过类的 new 方法实现

  • 第一次创建对象并保存到类属性中
  • 后续从类属性中取出对象,不再创建新的对象
class SingleClass():
    def __new__(cls, *args, **kwargs):
        print('new instance for ', cls)
        
        if not hasattr(cls, '__instance__'):
            print('create instance for ', cls)
            instance = super(SingleClass, cls).__new__(cls, *args, **kwargs)
            cls.__instance__ = instance
        
        return cls.__instance__


class SubClass(SingleClass):
    pass

test00 = SingleClass()
test01 = SingleClass()
print(test00, test01)

print('\n----------------------\n')

test10 = SubClass()
test11 = SubClass()
print(test10, test11)
new instance for  <class '__main__.SingleClass'>
create instance for  <class '__main__.SingleClass'>
new instance for  <class '__main__.SingleClass'>
<__main__.SingleClass object at 0x7f5492fc75f8> <__main__.SingleClass object at 0x7f5492fc75f8>

----------------------

new instance for  <class '__main__.SubClass'>
new instance for  <class '__main__.SubClass'>
<__main__.SingleClass object at 0x7f5492fc75f8> <__main__.SingleClass object at 0x7f5492fc75f8>

我们发现这样实现是有问题的,SubClass 无法创建自己的单例。 因为父类 SingleClass 的类对象数据会被所有子类共享,导致所有 SingleClass 子类无法创建新的对象。

解决方法是我们在 SingleClass 类中使用字典保存每个子类的实例对象,改进后代码如下:

class SingleTClass():
    __instance__ = {}
    
    def __new__(cls, *args, **kwargs):
        print('new instance for ', cls)
        
        if not cls in cls.__instance__:
            print('create instance for ', cls)
            instance = super(SingleTClass, cls).__new__(cls, *args, **kwargs)
            cls.__instance__[cls] = instance

        return cls.__instance__[cls]


class SubTClass(SingleTClass):
    pass

test00 = SingleTClass()
test01 = SingleTClass()
print(test00, test01)

print('\n----------------------\n')

test10 = SubTClass()
test11 = SubTClass()
print(test10, test11)
new instance for  <class '__main__.SingleTClass'>
create instance for  <class '__main__.SingleTClass'>
new instance for  <class '__main__.SingleTClass'>
<__main__.SingleTClass object at 0x7f5492fc7ac8> <__main__.SingleTClass object at 0x7f5492fc7ac8>

----------------------

new instance for  <class '__main__.SubTClass'>
create instance for  <class '__main__.SubTClass'>
new instance for  <class '__main__.SubTClass'>
<__main__.SubTClass object at 0x7f5492fc7438> <__main__.SubTClass object at 0x7f5492fc7438>

3. 通过装饰器实现单例

  • 创建一个 singleclass 的装饰器
  • 创建类的时候使用上述装饰器
from functools import wraps

"""
把类对象变成一个函数,每次调用类对象创建实例的时候,实际是调用装饰器返回的函数
"""
def singleclass(cls):
    __instance__ = {}
    
    @wraps(cls)
    def cls_instance(*args, **kwargs):
        print('new instance for ', cls)
        if not cls in __instance__:
            __instance__[cls] = cls(*args, **kwargs)
        return __instance__[cls]

    return cls_instance

@singleclass
class TestD1Class():
    pass

@singleclass
class TestD2Class():
    pass



test00 = TestD1Class()
test01 = TestD1Class()
print(test00, test01)

print('\n----------------------\n')

test10 = TestD2Class()
test11 = TestD2Class()
print(test10, test11)
new instance for  <class '__main__.TestD1Class'>
new instance for  <class '__main__.TestD1Class'>
<__main__.TestD1Class object at 0x7f5492fee518> <__main__.TestD1Class object at 0x7f5492fee518>

----------------------

new instance for  <class '__main__.TestD2Class'>
new instance for  <class '__main__.TestD2Class'>
<__main__.TestD2Class object at 0x7f5492fee160> <__main__.TestD2Class object at 0x7f5492fee160>

以上所述就是小编给大家介绍的《python 单例模式》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

小圈子·大社交

小圈子·大社交

Paul Adams / 王志慧 / 人民邮电出版社 / 2013-1 / 29.00元

网络正在脱离以内容为核心构建的方式,转向以人为核心重新构建。这样深远的变革将影响我们制定商业策略、设计以及营销和广告的方式。 本书作者先后在谷歌和Facebook供职,对于社交网络有深入的研究和丰富的实战经验。他以学术界和工业界最新的调查研究为基础,阐述了人们如何通过社交圈子相互联系的规律,探讨了理念和品牌信息如何通过社交网络传播开来的过程。书中介绍了许多实际的例子,通过这些鲜活的实例,你将......一起来看看 《小圈子·大社交》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具