美文网首页Python
Python3实现单例模式

Python3实现单例模式

作者: Closears | 来源:发表于2018-04-24 01:47 被阅读406次

文末有一些补充内容,如果你不太理解本文中提到的这些函数的意义或者不知道元类是什么东西,可以先查看补充内容,以帮助你做好理解本文所必要的知识储备

1. 在进入正题之前,我们需要先了解两个有特殊用途的函数,
__new__()__call__().

__new__()
它是在创建实例的时候被调用(注意此处的"实例",我在这里并没有说"的实例",因为除了类,还有元类,元类创建实例的时候也会调用这个函数)

__call__()
官方定义:Called when the instance is "called" as a function; if this method is defined, x(arg1, arg2, ...) is a shorthand for x.__call__(arg1, arg2, ...).
它是在“实例被当成函数调用时”被调用。
举个例子,实例如果是"Demo",那么,当你写下"Demo()"的时候,该实例(即Demo)的创建者(注意:此处提到的创建者既有可能是类,也有可能是元类)中的__call__()被调用。

如果这个实例是一个类,那么它的创建者就是一个元类,如果这个实例是一个对象,那么它的创建者就是一个类。

所以,要利用Python实现单例模式,我们也有两种思路:

2. (下面是正题,我们来谈一谈如何在Python3中实现单例模式):

第一种思路是利用元类,元类的实例是类,而类被当成函数调用时不就是对象吗?(假设类名是Demo,则Demo()就创建并返回了一个对象)因此,我们可以通过定制元类中的__call__()来实现单例。
代码如下:

class Singleton(type):
    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = super().__call__(*args, **kwargs)
        return cls._instance

class Foo(metaclass=Singleton):
    pass

这里,Foo是元类"Singleton"的实例,Foo()就是元类"Singleton"的实例被当成函数在调用,因此元类"Singleton"中的__call__()就会被调用。

我们输入以下代码来测试一下:

a = Foo()
b = Foo()
print(id(a)==id(b))  # 得到 True

第二种思路则不需要用到元类。
由于__new__()是在创建实例的时候被调用(即,如果你创建一个类Foo,并且这个Foo中含有一个__new__()的方法,那么该方法将在你创建这个Foo类的对象时被调用,即在你写Foo()的时候被调用),所以我们可以通过直接定制__new__()来实现单例。
代码如下:

class Foo(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = super().__new__(cls, *args, **kwargs)
        return cls._instance

测试一下:

a = Foo()
b = Foo()
print(id(a)==id(b))  # 得到 True

当然,如果你不想在当前这个类中定制__new__()方法,你也可以在当前类的父类中定制__new__(),python的解释器依然能够找到并正确执行这个函数,毕竟子类已经继承了父类的方法了。如下:

class Singleton(object):
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            cls._instance = super().__new__(cls, *args, **kwargs)
        return cls._instance

class Foo(Singleton):
    pass

再测试一下:

a = Foo()
b = Foo()
print(id(a)==id(b))  # 得到 True

以上就是本篇教程的全部核心内容,谢谢您的阅读!

补充内容:

  1. 什么是元类?
    简单回答:对象的抽象化是类,而类的抽象化就是元类,或者说,对象是类的实例,类就是元类的实例,还可以说,类具体化后得到对象,元类具体化后得到类。
    具体回答:详见本博客的后续博文。

  2. 诸如以上提到的__new__()__call__()这类函数,它们存在的意义是什么?我们到底为什么需要它们?
    :以上这样的函数还有很多,它们最主要的用途就是帮助我们定制化我们自己的类,让类的功能更符合我们的需求。

相关文章

  • Android设计模式总结

    单例模式:饿汉单例模式://饿汉单例模式 懒汉单例模式: Double CheckLock(DCL)实现单例 Bu...

  • python面试题-2018.1.30

    问题:如何实现单例模式? 通过new方法来实现单例模式。 变体: 通过装饰器来实现单例模式 通过元类来创建单例模式...

  • 单例模式

    一、实现单例模式 或者 二、透明的单例模式 三、用代理实现单例模式 四、JavaScript中的单例模式 在Jav...

  • 单例模式和GCD单例实现

    1、传统单例模式2、GCD单例模式3、用宏实现GCD单例模式4、用宏实现GCD单例模式,名称随类名变化而变化 单例...

  • kotlin实现单例模式

    1.懒汉式实现单例模式 2.线程安全懒汉式实现单例模式 3.双重校验懒汉式实现单例模式 4.静态内部类方式实现单例模式

  • 单例模式之枚举类enum

    通过枚举实现单例模式 枚举类实现单例模式的优点 对于饿汉式单例模式和懒汉式单例模式了解的同学,使用以上两种单例模式...

  • 单例模式

    单例模式及C++实现代码单例模式4种实现详解 c++11改进我们的模式之改进单例模式 单例模式(Singleton...

  • 单例模式

    饿汉模式: 懒汉模式: Double CheckLock(DCL)实现单例 静态内部类实现单例 枚举单例 使用容器...

  • iOS 单例

    单例模式实现不能使用继承 定义单例实现 简写 定义单例实现宏

  • 设计模式--单例模式

    单例模式概述 单例模式实现方式 为什么要使用单例模式 单例模式实现方式 饿汉式 类加载后就会将对象加载到内存中,保...

网友评论

    本文标题:Python3实现单例模式

    本文链接:https://www.haomeiwen.com/subject/vjqdlftx.html