__new__() 与 __init__() 的区别;
1.首先用法不同,new()用于创建实例,所以该方法是在实例创建之前被调用,它是类级别的方法,是个静态方法;
而 init() 用于初始化实例,所以该方法是在实例对象创建后被调用,它是实例级别的方法,用于设置对象属性的一些初始值。
由此可知,new()在__init__() 之前被调用。如果__new__() 创建的是当前类的实例,会自动调用__init__()函数,通过return调用的__new__()的参数cls来保证是当前类实例,如果是其他类的类名,那么创建返回的是其他类实例,就不会调用当前类的__init__()函数。
2.其次传入参数不同
new()至少有一个参数cls,代表当前类,此参数在实例化时由Python解释器自动识别;
init()至少有一个参数self,就是这个__new__()返回的实例,init()在__new__()的基础上完成一些初始化的操作。
3.返回值不同
new()必须有返回值,返回实例对象;
init()不需要返回值。
另外谈谈__new__()的作用,new()方法主要用于继承一些不可变的class,比如int, str, tuple, 提供一个自定义这些类的实例化过程的途径,一般通过重载__new__()方法来实现
new()方法还可以用来实现单例模式,也就是使每次实例化时只返回同一个实例对象。
单例模式:
1.文件导入
class Foo(object):
def test(self):
print('123')
v = Foo()
from test01 import v as v1
print(v1,id(v1))
from test01 import v as v2
print(v2,id(v2))
2.装饰器
from functools import wraps
def singleton(cls):
instances = {}
@wraps(cls)
def wrapper(*args,**kwargs):
if cls not in instances:
instances[cls] = cls(*args,**kwargs)
return instances[cls]
return wrapper
@singleton
class Fun01(object):
a = 1
m1 = Fun01()
m2 = Fun01()
print(id(m1))
print(id(m2))
注:加上functools的wrap,它能保留原有函数的名称和docstring
3.类方法
import time
import threading
class Singleton(object):
_instance_lock = threading.Lock()
def __init__(self,*args,**kwargs):
time.sleep(1)
@classmethod
def get_instance(cls,*args,**kwargs):
if not hasattr(Singleton,'_instance'):
with Singleton._instance_lock:
if not hasattr(Singleton,'_instance'):
Singleton._instance = Singleton(*args,**kwargs)
return Singleton._instance
def task(arg):
obj = Singleton.get_instance(arg)
print(obj)
for i in range(10):
t = threading.Thread(target=task,args=[i,])
t.start()
obj = Singleton.get_instance()
print(obj)
这种方式创建的单例,必须使用Singleton_get_instance()方法,如果使用Singleton()的话,得到的并不是单例.所以我们推荐使用__new__()方法来创建单例,这样创建的单例可以使用类名()的方法进行实例化对象
4.new方法
class Singleton(object):
def __init__(self):
pass
def __new__(cls, *args, **kwargs):
if not hasattr(cls,'_instance'):
cls._instance = super().__new__(cls,*args,**kwargs)
return cls._instance
s1 = Singleton()
s2 = Singleton()
print(id(s1))
print(id(s2))
5.使用元类
class Singleton(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
class MyClass(metaclass=Singleton):
pass
m1 = MyClass()
m2 = MyClass()
print(id(m1))
print(id(m2))
元类(metaclass)可以控制类的创建过程,它主要做三件事:
1. 拦截类的创建
2.修改类的定义
3.返回修改后的类