- 1. __new__和__init__方法的区别
- 2. 单例模式
- 2.1 什么是单例
- 2.2 单例模式
我们先看一个例子:
class Idol(object):
def __new__(cls, name, age):
print('__new__ called')
return super(Idol, cls).__new__(cls)
def __init__(self, name, age):
print('__init__ called')
self.name = name
self.age = age
def __str__(self):
return 'Idol: %s-%s' % (self.name, self.age)
if __name__ == '__main__':
name = Idol('kobe', 24)
print(name)
实例化一个对象,输出结果:
__new__ called __init__ called Idol: kobe-24
通过这段代码我们看到,实例化一个类的时候,new 方法的调用发生在 init 之前。实例化一个类的语句为 p = Idol(name, age),其具体的执行逻辑如下:
- 首先执行 Idol 类的 new 方法,这个 new 方法会返回 Idol 类的一个实例(通常情况下是使用 super(Idol, cls).new(cls)这样的方式);
- 然后利用这个实例来调用类的 init 方法,上一步里面 new 产生的实例也就是 init 里面的的 self。
由此,init 和 new 的区别在于:
- new 通常用于控制生成一个新实例的过程。它是类级别的方法。
- new 至少要有一个参数 cls,代表要实例化的类,该参数在实例化时由 Python 解释器自动提供;
- new 必须要有返回值,返回实例化出来的实例;
- init 通常用于初始化一个新实例,控制这个初始化的过程,比如添加一些属性,做一些额外的操作,发生在类实例被创建完以后。它是实例级别的方法。
确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类。
例如,我们电脑的回收站就是单例模式,在整个操作系统中,回收站只能有一个实例,整个系统都使用这个唯一的实例,而且回收站自行提供自己的实例。
2.2 单例模式class Singleton(object):
__instance = None
def __new__(cls, num, name):
# 先判断是否有这个类的实例,没有就实例化一个并赋值给引用,有就直接返回该实例,以此保证单例
if not cls.__instance:
cls.__instance = super(Singleton, cls).__new__(cls)
return cls.__instance
def __init__(self, num, name):
self.num = num
self.name = name
if __name__ == '__main__':
a = Singleton(24, "kobe")
print(id(a))
print(a.num)
b = Singleton(30, "curry")
print(id(b))
print(b.num)
输出:
140392531769904 24 140392531769904 30
由输出我们看到,上面的代码实现了 Singleton 类的单例;同时我们也发现,单例类的 __new__ 方法只能调用一次,但 __init__ 方法会调用多次,我们可以在 __init__ 方法中修改属性。
我们也可以实现只执行一次 __init__ 方法的单例,通过在 __init__ 方法中增加一个标志位来实现,如下:
class Singleton(object):
__instance = None
__first_init = False
def __new__(cls, num, name):
# 先判断是否有这个类的实例,没有就实例化一个并赋值给引用,有就直接返回该实例,以此保证单例
if not cls.__instance:
cls.__instance = super(Singleton, cls).__new__(cls)
return cls.__instance
def __init__(self, num, name):
if not self.__first_init:
self.num = num
self.name = name
self.__first_init = True
if __name__ == '__main__':
a = Singleton(24, "kobe")
print(id(a))
print(a.num)
b = Singleton(30, "curry")
print(id(b))
print(b.num)
输出:
139650736351792 24 139650736351792 24



