单例模式

__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.返回修改后的类
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值