专栏首页软件测试小助手python单例模式你搞懂了么?我是终于懂了~

python单例模式你搞懂了么?我是终于懂了~

在看面试题的时候,突然想到以前有人问我你知道什么是单例模式么?当时的我 一脸懵逼,更别说让我写下来了,后来也没总结整理,今天就来记录下python的单例模式是什么样的,应该经常会在面试题中问到,感兴趣的小伙伴可以看看哦~

一、概念

单例模式的作用就是确保某一个类只有一个实例存在,减少多次调用实体类造成的资源浪费。

比如:在创建一个config对象的时候,要获取里面的配置文件,但是其他类也需要使用该文件,就会导致很多地方都创建实例化对象,占用内存资源,所以我们要在程序中配置只存在一个实例对象。

tips:我的一直认为像这样的代码即使不理解,拼死也要背下来,万一面试官让你写下来呢?

一、通过文件导入实现单例

代码如下:

# 创建Singleton.py文件
class A(object):
    def foo(self):
       print('test')
v = A()
===============================================
# 创建另一文件,调用该实例
from singleton import A as a1
from singleton import A as a2

print(a1, id(a1))
print(a2, id(a2))

结果:多次导入该实例,其实调用的是同一个地址

二、通过__new__方法

主要思路:在一个类的new方法中判断是不是存在实例,如果存在就直接返回,不存在就创建。

class singleton(object):
    def __init__(self):
        pass
    def __new__(cls, *args, **kwargs):
        # 是否有实例,没用则创建一个实例
        if not hasattr(cls, '_instance'):
            singleton._instance = object.__new__(cls)
        return singleton._instance
obj1 = singleton()
obj2 = singleton()
print(obj1, obj2)

三、装饰器

装饰器:把其他函数作为参数的函数,简单来说,就是修改其他函数功能的函数。(可以看下 什么是Python装饰器

思路:装饰器外部变量定义一个字典存放类的实例,第一次创建的时候,把实例保存到字典中,每次创建对象的时候,判断是否实例化过,若没有则去实例,若没有则保存该实例到字典中。

def Singleton(cls, *args, **kargs):
    _instance = {}  # 创建空字典
    def get_instance(*args, **kargs):
        if cls not in _instance:
            _instance[cls] = cls(*args, **kargs)
        return _instance[cls]  # 返回实例
    return get_instance  # 返回内层函数

@Singleton 
class Settings():
    def __init__(self):
        self.a = 'abc'
s1 = Settings()
s2 = Settings()
print(s1, s2)

结果:

四、classmethod类方法

import time
import threading
class Singleton(object):
     _instance_lock = threading.Lock() # 加锁
    def __init__(self):
        time.sleep(1)        
    @classmethod
    def instance(cls, *args, **kwargs):
        with Singleton._instance_lock: # 加锁
            if not hasattr(Singleton, '_instance'):
                Singleton._instance = Singleton(*args, **kwargs)
            return Singleton._instance
def test(arg):
    obj1 = Singleton.instance()
    obj2 = Singleton.instance()
    print(obj1, obj2)

但是这里要主要的是,存在多线程的时候,并不是同一个内存地址,所以要加锁,让多线程的时候也使用同一个内存地址。

本文分享自微信公众号 - 软件测试小助手(gh_2282fef3410c),作者:小雯子打豆豆

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-05-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Jmeter之数据库连接池--select、update、callable

    Jmeter是个超级强大的性能测试工具,同上也可以跑接口测试,也可以对任何数据库做测试。今天给大家分享下如何通过Jmeter连接数据库并做一下数据操作。

    小雯子打豆豆
  • pytest+yaml实现接口自动化

    最近在学pytest的使用,不同于httprunner自动化测试框架,创建项目的时候就能把所有的项目文件目录整理出来,需要手动创建文件分类,不管怎么样,先学会用...

    小雯子打豆豆
  • 测试学习成长之路

    作为一个从开发转测试的职场小白,虽然说不上是个技术大牛,不过靠自己的积累也算收获了很多,下面就自己三年的工作经验,总结一下,也给一些刚入门的测试同学们一些经验分...

    小雯子打豆豆
  • python实现单例模式详解

    缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。 使用场景:

    渔父歌
  • Groovy单元测试框架spock数据驱动Demo

    上次文章分享了spock框架的基础功能的使用,在此基础上,我根据自己写的Groovy的封装方法、数据驱动以及一些Groovy的高级语法做了一些尝试。发现还是有一...

    八音弦
  • #include<stdio.h>,为什么C语言代码开头都有这一行?

    #include<stdio.h>是在程序编译之前要进行处理的的内容,因此也称为预处理命令。

    闫小林
  • tf.compat.v1.MetaGraphDef

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    于小勇
  • 关于Laravel使用队列后台发送邮件

    今天要用到后台使用队列发送邮件,于是又稍微去了解了下Laravel中使用队列。其实在最开始用Laravel写博客【 https://www.misiyu.cn...

    无道
  • 门上不再有开锁小广告的今天,开锁公司如何应时应势,绝地逢生

    用户1745481
  • Python中的类、对象、继承

    上述访问级别更多的是一种编程约定,即便是以双下划线开头的字段,在类的外部也是可以访问的,但不建议这么做。示例代码如下:

    雪飞鸿

扫码关注云+社区

领取腾讯云代金券