Python 中 Singleton 的写法及其拓展

栏目: Python · 发布时间: 6年前

内容简介:Python 中 Singleton 的写法及其拓展

重要性无需多言,我们在项目中经常有「要一个进程全局的变量(内存块)」的需求,而且单例模式是几种 设计模式 中最容易的。

偷懒且有用的做法:模块级别常量

我经常使用这种方式,因为简单且不易出错。

众所周知,Python 的 module 概念,是一个天然的 Singleton。而且 Python 是多范式语言,可以不必像 Java 那样使用 class 去处理这件事情,在 module 级别定义一个常量,是一种很自然的想法。

代码如下:

  • 定义方
singleton.py

class _MySingleton(object):
    """
    我们使用下划线开头, 告诫调用者, 不要直接 new
    也不要来访问这个class
    """
    def __init__(self, name, age):
        self._name = name
        self._age = age

    def print_name(self):
        print(self._name)

# 可以定制多个全局实例
S1 = _MySingleton('s1', 22)
S2 = _MySingleton('s2', 11)
  • 调用方
caller.py

from singleton import S1

# 尽情使用S1( 在任意点import 都可以 ), 它是全局唯一的!

正规做法:元编程

有些人不喜欢上面那种做法,他们认为「破坏了代码的纯粹性」,这个时候我们可以使用元编程的方式,让我们更近一步。

这是从 Python Cookbook 摘取出来的代码。

  • 元类基类
class SingletonMetaclass(type):
    def __init__(self, *args, **kwargs):
        self.__instance = None
        super().__init__(*args, **kwargs)

    def __call__(self, *args, **kwargs):
        if self.__instance is None:
            self.__instance = super(SingletonMetaclass, self).__call__(*args, **kwargs)
            return self.__instance
        else:
            return self.__instance
  • 继承了元类基类的类
class SpamSingleton(metaclass=SingletonMetaclass):
    """注意: 根据Singleton的定义, 构造函数一般需要使用默认的构造函数"""
    def get_addr(self):
        return id(self)
  • 调用方
from singleton import SpamSingleton

s1 = SpamSingleton()
s2 = SpamSingleton()

pritn(id(s1), id(s2))   # 内存地址是一样的

老实说,理解 SingletonMetaclass 的作用过程还是有点困难的,我花了好久才搞清楚上面各个方法的调用流程。

不过 SingletonMetaclass 的作用也是巨大的,我们定义将其放入一个 base.py 的文件中,任何时刻我们想要定义某个 Singleton class,直接从其继承即可,简单且方便。

比较 Hack 的做法:Borg 模式

不多说,搜索引擎搜出来的结果,全都是推荐这种做法,让人以为这是「主流做法」(其实并不是)。

这种做法,修改了 Singleton 的定义,即:所有变量共享一个内存块,但是这个内存块的内容是可变化的。然后通过将实例的 __dict__ 方法重定向 class 的 __dict__ 方法,以达到其目的。

但是这种做法不是很符合我对 Singleton的感知,即:全局唯一,且其内容最好也不要变化。所以在实际开发中,并不喜欢这种做法。

总结

从个人的倾向来看,比较喜欢「掌握一种或两种方式,然后使用最熟练,而且不出错」的观点,所以我只推荐第一二种方式。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Servlet&JSP学习笔记

Servlet&JSP学习笔记

林信良 / 清华大学出版社 / 2010-4 / 48.00元

《Servlet&JSP学习笔记》以“在线书签”项目贯穿全书,随着每一章的讲述都在适当的时候将 Servlet & JSP技术应用于“在线书签”程序之中,并作适当修改,以了解完整的应用程序构建方法。《Servlet&JSP学习笔记》内容包括简单的Web应用程序,开发简单的Servlet & JSP合理管理,JSP的使用,整合数据库等相关内容,《Servlet&JSP学习笔记》适合Servlet ......一起来看看 《Servlet&JSP学习笔记》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

MD5 加密
MD5 加密

MD5 加密工具