zoukankan      html  css  js  c++  java
  • python单例模式控制成只初始化一次,常规型的python单例模式在新式类和经典类中的区别。

    单例模式的写法非常多,但常规型的单例模式就是这样写的,各种代码可能略有差异,但核心就是要搞清楚类属性 实例属性,就很容易写出来,原理完全一模一样。

    如下:

    源码:

    class A(object):
        def __new__(cls, *args, **kwargs):
            if not hasattr(cls, '__inst'):
                print('执行new')
                obj = super(A, cls).__new__(cls)
                setattr(cls, '__inst', obj)
                return obj
            else:
                return cls.__dict__['__inst']
    
        def __init__(self, x):
            print('执行init')
            self.x = x
    
    
    if __name__ == '__main__':
        a1 = A(1)
        print('a1.x ', a1.x)
        a2 = A(2)
        print('a2.x ', a2.x)
        print('a1.x ', a1.x)
        a3 = A.__new__(A)
        # a3.__init__(3)                    # a3 = A(3) 实际是调用了new和init方法,此处屏蔽调用init
        print('a3.x ', a3.x)
        print(id(a1), id(a2), id(a3))

    实例化了三个对象,执行结果可以猜猜:

    可以发现,执行了一次new,但执行了两次init,这是在新式类下运行的,python3默认是新式类,不管有没有继承object。

    如果是python2,且不继承object,实际上是只会打印执行一次init。所以这是py2和py3的又一个区别,经典类和新式类区别非常多,新式类的反射方法也与经典类有些不同。但一般文章只说新式类和经典类的区别只是广度优先和深度优先,误导。

    3、终极目标就是使python3的实例也不多执行力一次init,(因为虽然单例模式能控制成是所有类的实例指向同一个对象,但有时候的单例模式初始化是建立一个io连接或者资源池,这样每次执行初始化浪费一些时间)

    三种方法,一种是增加一个类属性做标志,在init方法中增加if判断

    第二种是,不使用 a = A(xxxx),而使用a = A.__new__(A),因为a = A(xxxx),实际上是a = A.__new__(A),和a.__init__(xxx) 

    第三种是自己写一个名字例如叫  _custom_init的方法,不写__init__方法,在new中生成self(就是实例),new里面显式手动调用此方法,这样也可以避免自动执行__init__

    4、还有一种方式是使用装饰器,如果按照这个写法也不会执行多次init

    单例模式装饰器

    #coding=utf8
    from functools import wraps
    
    
    def singleton(cls):
        print cls
        instances = {}
        @wraps(cls)
        def getinstance(*args, **kw):
            if cls not in instances:
                instances[cls] = cls(*args, **kw)
            return instances[cls]
        return getinstance
    
    
    @singleton
    class MyClass(object):
        a = 1
    
    m1=MyClass()
    m2=MyClass()
    
    print m1 is m2

    或者元类单例模式,

    单例模式元类

    5、在实际项目中我用的单例模式有一些,不是很多,享元模式就可以了,享元模式是对一个重点属性在不同对象中保证该属性是指向同一个对象,使用更为灵活,这个重点属性通常是一个io连接或资源池,或者计算代价十分大的东西,以免造成实例化浪费巨大的时间。

  • 相关阅读:
    [转]我们应该做什么样的研究
    [转]面向服务架构(SOA)和企业服务总线(ESB)
    [转]程序员应知——团队精神
    vs2010 调试快捷键
    asp.net 获取ip的6种方法
    解决了防止用户重复登陆和session超时
    IE 10 也能随网站应变,图标决定一切!
    Sony VAIO Duo 11 游戏性能测试
    翻出Windows 8 当中的游戏管理器
    Office 2013预览版已到期,需要付费才可正常使用
  • 原文地址:https://www.cnblogs.com/ydf0509/p/9463832.html
Copyright © 2011-2022 走看看