zoukankan      html  css  js  c++  java
  • 由Python通过__new__实现单例模式,所想到的__new__和__init__方法的区别

            之前通过读书,了解到在Python中可以通过__new__方法来实现单例模式,代码一个示例如下,我就有了几个疑问,什么是单例模式?__new__方法是用来做什么的?用__new__方法实现的单例模式,比如下面的MyClass类,会对类的初始化有影响吗?会对类的实例方法、类方法、静态方法有影响吗?下面会说下我对这些概念的理解,如有错误,欢迎交流指出,在此表示感谢。

     1 class SingleTon(object):
     2     _instance = {}
     3 
     4     def __new__(cls, *args, **kwargs):
     5         if cls not in cls._instance:
     6             cls._instance[cls] = super(SingleTon, cls).__new__(cls, *args, **kwargs)
     7         print cls._instance
     8         return cls._instance[cls]
     9 
    10 
    11 class MyClass(SingleTon):
    12     class_val = 22

          首先说下单例模式,单例模式是确保一个类只有一个实例,并且这个实例是自己创造的,在系统中用到的都是这个实例。单例模式是设计模式的一种,关于设计模式和单例模式更具体的内容,可以查看相关的书本,在后面我也要好好学习一下这些东西。

        下面主要说下__new__是用来干什么的,在Python中,__new__是用来创造一个类的实例的,而__init__是用来初始化这个实例的。既然__new__用来创造实例,也就需要最后返回相应类的实例,那么如果返回的是其他类的实例,结果如何呢?见下面的代码。以下代码运行后,首先打印出NoReturn __new__然后打印出other instance,最后通过type(t)可以看到t的类型是<class '__main__.Other'>,可以知道如果__new__中不返回本类的实例的话,是没法调用__init__方法的。想要返回本类的实例,只需要把以下代码中12行的Other()改成super(NoReturn, cls).__new__(cls, *args, **kwargs)即可。

     1 class Other(object):
     2     val = 123
     3 
     4     def __init__(self):
     5         print 'other instance'
     6 
     7 
     8 class NoReturn(object):
     9 
    10     def __new__(cls, *args, **kwargs):
    11         print 'NoReturn __new__'
    12         return Other()
    13 
    14     def __init__(self, a):
    15         print a
    16         print 'NoReturn __init__'
    17 
    18 t = NoReturn(12)
    19 print type(t)

           

           最后来说用__new__方法实现的单例模式,会对实例方法,类方法,静态方法,实例变量和类变量有影响吗?答案是对相应的方法是没有影响的,但是如果用不同的变量都初始化了这个实例,在后面的变量中修改实例变量和类变量的话,前面的也会相应修改,而这也正好符合单例,无论多少个变量指向了这个实例,他们指向的是同一个。在__new__中产生完实例后,每次初始化实例对象,都是产生的同一个实例,而这个实例中相关的方法、变量还是和普通的实例一样使用。测试代码以及输出如下:

     1 class MyClass(SingleTon):
     2     class_val = 22
     3 
     4     def __init__(self, val):
     5         self.val = val
     6 
     7     def obj_fun(self):
     8         print self.val, 'obj_fun'
     9 
    10     @staticmethod
    11     def static_fun():
    12         print 'staticmethod'
    13 
    14     @classmethod
    15     def class_fun(cls):
    16         print cls.class_val, 'classmethod'
    17 
    18 
    19 if __name__ == '__main__':
    20     a = MyClass(1)
    21     b = MyClass(2)
    22     print a is b   # True
    23     print id(a), id(b)  # 4367665424 4367665424
    24     # 类型验证
    25     print type(a)  # <class '__main__.MyClass'>
    26     print type(b)  # <class '__main__.MyClass'>
    27     # 实例方法
    28     a.obj_fun()  # 2 obj_fun
    29     b.obj_fun()  # 2 obj_fun
    30     # 类方法
    31     MyClass.class_fun()  # 22 classmethod
    32     a.class_fun()  # 22 classmethod
    33     b.class_fun()  # 22 classmethod
    34     # 静态方法
    35     MyClass.static_fun()  # staticmethod
    36     a.static_fun()  # staticmethod
    37     b.static_fun()  # staticmethod
    38     # 类变量
    39     a.class_val = 33
    40     print MyClass.class_val  # 22
    41     print a.class_val  # 33
    42     print b.class_val  # 33
    43     # 实例变量
    44     print b.val  # 2
    45     print a.val  # 2
  • 相关阅读:
    《JAVA与模式》之备忘录模式
    《JAVA与模式》之调停者模式
    如何将GTK+2.0的信号、回调处理映射成类成员函数的调用VC中测试(单类继承)
    第一个GTK程序:中国农历 附录2 libtool
    【转载】成员函数指针与高性能的C++委托
    第一个GTK程序:中国农历 附录4 动态库
    第一个GTK程序:中国农历 附录3 静态库
    【转载】C++中实现委托(Delegate)
    如何将GTK+2.0的信号、回调处理映射成类成员函数的调用VC中测试(虚拟继承类及多继承)
    第一个GTK程序:中国农历 附录5 变量名
  • 原文地址:https://www.cnblogs.com/qiaojushuang/p/7805973.html
Copyright © 2011-2022 走看看