由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
时间: 2024-07-31 13:42:59

由Python通过__new__实现单例模式,所想到的__new__和__init__方法的区别的相关文章

python中单例模式的实现-通过闭包函数和魔术方法__new__实现单例模式

1.通过闭包函数实现单例模式: # 使用闭包函数实现单例 def single(cls, *args, **kwargs): instance = {} def get_instance(): if cls not in instance: instance[cls] = cls(*args, **kwargs) return instance[cls] return get_instance @single class Apple: pass a = Apple() b = Apple() p

Python下简易的单例模式详解(转)

Python 下的单例模式 要点: 1.某个类只能有一个实例: 2.它必须自行创建这个实例: 3.它必须自行向整个系统提供这个实例 方法:重写new函数 应该考虑的情况: 1.这个单例的类可能继承了别的类 2.这个单例的类还有可能要接收参数来实例化 要点: 实例化的过程其实不是直接调用init的,首先是new分配一块空间来创建实例,再由init对这个实例进行初始化.我们无法阻止new和init的调用,我们只能是限制他们的内容,以此使他们能达到单例的目的 代码: ? 1 2 3 4 5 6 7 8

Python设计模式之一(单例模式)

单例模式就是告诉你,只有一个对象 (1)单例模式不适用的场景 #单例模式就是告诉你,其实只有一个对象 class Person: def __init__(self,name,age): self.name = name self.age = age ''' 假设这样一个场景,有一个专门创造人的这样一个类,在我们每实例化创造一个人的时候, 我们要赋予这个人姓名,年龄,基本,身高,等等,这种模式明显不适用单例模式,因为有多个对象, 且每个对象都封装了不同属性,单例模式则只能允许创建一个人,所以不适

Python中__init__方法

注意1.__init__并不相当于C#中的构造函数,执行它的时候,实例已构造出来了. 1 2 3 4 5 class A(object):     def __init__(self,name):         self.name=name     def getName(self):         return 'A '+self.name 当我们执行 1 a=A('hello') 时,可以理解为 1 2 a=object.__new__(A) A.__init__(a,'hello')

python中的__init__方法

init()方法意义重大的原因有两个.第一个原因是在对象生命周期中初始化是最重要的一步:每个对象必须正确初始化后才能正常工作.第二个原因是init()参数值可以有多种形式. __init__方法使用 1.使用demo 初始化 .注意,这个名称的开始和结尾都是双下划线.使用__init__方法代码例子 #!/usr/bin/python # Filename: class_init.py class Person: def __init__(self, name): self.name = nam

Python统计列表中的重复项出现的次数的方法

前言 在实际工作和学习中,经常会遇到很多重复的数据,但是我们又必须进行统计,所及这里简单介绍一下统计列表中重复项的出现次数的简单方法. 实例 本文实例展示了Python统计列表中的重复项出现的次数的方法,是一个很实用的功能,适合Python初学者学习借鉴.具体方法如下: #方法1: mylist = [1,2,2,2,2,3,3,3,4,4,4,4] myset = set(mylist)  #myset是另外一个列表,里面的内容是mylist里面的无重复 项 for item in myset

java——多线程——单例模式的static方法和非static方法是否是线程安全的?

单例模式的static方法和非static方法是否是线程安全的? 答案是:单例模式的static方法和非static方法是否是线程安全的,与单例模式无关.也就说,如果static方法或者非static方法不是线程安全的,那么不会因为这个类使用了单例模式,而变的安全. 闲话休说,看代码: import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class TestSingl

【机器学习算法-python实现】协同过滤(cf)的三种方法实现

(转载请注明出处:http://blog.csdn.net/buptgshengod) 1.背景 协同过滤(collaborative filtering)是推荐系统常用的一种方法.cf的主要思想就是找出物品相似度高的归为一类进行推荐.cf又分为icf和ucf.icf指的是item collaborative filtering,是将商品进行分析推荐.同理ucf的u指的是user,他是找出知趣相似的人,进行推荐.通常来讲icf的准确率可能会高一些,通过这次参加天猫大数据比赛,我觉得只有在数据量非

python 子类继承父类的__init__方法

父类A class A(object): def __init__(self, name): self.name=name print "name:", self.name def getName(self): return 'A ' + self.name 子类不重写__init__,实例化子类时,会自动调用父类定义的__init__ class B(A): def getName(self): return 'B '+self.name if __name__=='__main__