专业编程基础技术教程

网站首页 > 基础教程 正文

__new__|python3的基本单例方法就应该这么玩

ccvgpt 2024-08-10 12:38:30 基础教程 10 ℃

引言

不知道大家有没有这样的疑问?

桌面打开百度网盘登录之后,再次双击图标,返回的还是登录成功后的页面。

__new__|python3的基本单例方法就应该这么玩

微信PC版,登录一个账号之后,再次点击也只是回到了已经登录的账号页面。

......

诸如此类的现象还有很多,那么大家心里有没有疑问呢?为什么我再次点击登录也只是回到了第一次的界面呢?

这就是编程里面的单例思想设计模式的产物。

单例模式

单例模式,属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例)

__new__

__new__() 是一种负责创建类实例的静态方法,它无需使用 staticmethod 装饰器修饰,且该方法会优先 __init__() 初始化方法被调用。

举例说明一下

很显然,虽然我们实例化了p对象,但是因为由__new__方法存在,所以__init__方法并没有被执行。

那么如何让__init__也被执行呢?

return object.__new__(cls)
#!/usr/bin/env  python
class Printer():
    def __init__(self, app):
        self.app = app
        print("-----init------")
    def __new__(cls, *args, **kwargs):
    		#负责执行INIT方法
        print("----__new__-----")
				#类中的__new__方法被重写后,需要执行父类object中的__new__方法才可以继续执行__init__
        return object.__new__(cls)

p = Printer("word")
print(p.app)

执行结果就可以很清楚地看到,__init__被执行了

没有单例思想之前

这样的话就会有三个实例,其实只有一个是可以用的,资源浪费了。

单例模式设计之后

#!/usr/bin/env  python
class Printer():
    task = []
    __instance = None

    def __init__(self, app):
        self.app = app

    def __new__(cls, *args, **kwargs):

        if cls.__instance is None:
            obj = object.__new__(cls)
            print(obj)
            cls.__instance = obj
        return cls.__instance

    def add_task(self, job):
        self.task.append(job)
        print(f"{self.app}执行任务{job},任务总数是{len(self.task)}")

p1 = Printer("word")
p2 = Printer("excle")
p3 = Printer("pdf")
p1.add_task("word file print")
p2.add_task("excle file print")
p3.add_task("pdf file print")
print(p1, p2, p3)

执行结果:

"C:\Program Files\Python38\python3.exe" D:/python/python_210710/exercise_03/simple_example.py

<__main__.Printer object at 0x0000016A37D86C10>

pdf执行任务word file print,任务总数是1

pdf执行任务excle file print,任务总数是2

pdf执行任务pdf file print,任务总数是3

<__main__.Printer object at 0x0000016A37D86C10> <__main__.Printer object at 0x0000016A37D86C10> <__main__.Printer object at 0x0000016A37D86C10>

可知,此时的实例的内存地址都是C10,而且只保留了最后一个任务的打印操作。后面两次的实例化其实就是执行了__init__函数,并没有生成新的实例,只是对self.app做了修改。

总结

以上就是单例模式通过__new__方法的实现过程。

主要步骤为:

  1. 通过类变量作为参数,判断实例化准入条件
  2. 重写__new__方法,返回父类object的实例化对象object.__new__(cls)
  3. 调用__init__方法实现类的实例化

最近发表
标签列表