首页 > 编程语言 >Python单例的常用几种实现方法

Python单例的常用几种实现方法

时间:2023-04-28 10:55:11浏览次数:30  
标签:Python args 几种 Member instance ._ 单例 kwargs def

这两天在看自己之前写的代码,所以正好把用过的东西整理一下,单例模式,在日常的代码工作中也是经常被用到,

所以这里把之前用过的不同方式实现的单例方式整理一下。

装饰器的方式

这种方式也是工作中经常用的一种,用起来也比较方便,代码实现如下

def Singleton(cls):
    _instance = {}

    def _singleton(*args, **kwargs):
        if cls not in _instance:
            _instance[cls] = cls(*args, **kwargs)
        return _instance[cls]

    return _singleton

如果我们工作的一个类需要用单例就通过类似下面的方式实现即可:

@Singleton
class A(object):

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

我个人还是挺喜欢这种方式的

类的方式实现

这里其实有一些问题就需要注意了,先看一下可能出现的错误代码

class Member(object):

    @classmethod
    def instance(cls, *args, **kwargs):
        if not hasattr(Member, "_instance"):
            Member._instance = Member(*args, **kwargs)
        return Member._instance

乍一看这个类好像已经实现了单例,但是这里有一个潜在的问题,就是如果是多线程的情况,这样写就会有问题了,尤其是在当前类的初始化对象里有一些耗时操作时候

例如下面代码:

#! /usr/bin/env python3
# .-*- coding:utf-8 .-*-

import time
import threading
import random


class Member(object):
    
    def __init__(self):
        time.sleep(random.randint(1,3))

    @classmethod
    def instance(cls, *args, **kwargs):
        if not hasattr(Member, "_instance"):
            Member._instance = Member(*args, **kwargs)
        return Member._instance


def task(arg):
    obj = Member.instance()
    print(obj)

for i in range(5):
    t = threading.Thread(target=task, args=[i,])
    t.start()

这段代码的执行结果会出现实例化了多个对象,导致你写的单例就没起到作用

当然自然而然我们会想起加锁,通过锁来控制,所以我们将上面代码进行更改:

#! /usr/bin/env python3
# .-*- coding:utf-8 .-*-


import time
import threading
import random


class Member(object):
    _instance_lock = threading.Lock()

    def __init__(self):
        i = random.randint(1, 3)
        print(i)
        time.sleep(i)

    @classmethod
    def instance(cls, *args, **kwargs):
        with Member._instance_lock:
            if not hasattr(Member, "_instance"):
                Member._instance = Member(*args, **kwargs)
        return Member._instance


def task():
    obj = Member.instance()
    print(obj)

for i in range(5):
    threading.Thread(target=task,).start()

但是上面的代码还有一个问题,就是当我们已经实例化过之后每次调用instance都会去请求锁,所以这点并不好,所以我们将这部分代码再次更改:

@classmethod
    def instance(cls, *args, **kwargs):
        if not hasattr(Member, "_instance"):
            with Member._instance_lock:
                if not hasattr(Member, "_instance"):
                    Member._instance = Member(*args, **kwargs)
        return Member._instance

这样就很好的实现一个可以多线程使用的单例

标签:Python,args,几种,Member,instance,._,单例,kwargs,def
From: https://www.cnblogs.com/q-q56731526/p/17361508.html

相关文章

  • Python3+cgroupspy安装使用教程
    一、系统资源使用限制的必要性探讨对于一个脚本,最基础的限制是要限制单进程实例以保证了不会存在多个进程实例、在运行程序主体逻辑前检测系统资源剩余量确保自己不是压夸系统的最后一根稻草、设置程序运行超时时间以保证进程实例不会无休止地运行下去。进一步,在部署有可用性要......
  • Python3从头/尾删除子符串的正确操作
    一、说明从某个时候发现python的字符串变量自带的strip()方法,除了可以删除字符串头尾的空格,还可以用来删除头尾的字符串觉得很好用。也就一直这么用,一直也没发现什么问题。今天在修复一个bug时使用了strip()方法但从结果看bug并没有按预期被消除,一是没怀疑strip()删除子字符串有......
  • Python关于jsonpath路径里面包含中文或进行参数化的解决方案
    jsonpath路径包含中文当jsonpath路径包含中文时,我们只需要在jsonpath路径里面把中文用引号包裹即可准备json文件{"data":[{"Details":[{"姓名":"张三"}]}......
  • 单例模式
    一、线程安全性的讲解1、视频截图 2、线程安全性的代码加不加临界区进行验证1//!!!!!!!!!加C++泛型编程与STL开发实战QQ群:726114806下载代码和交流2#include<afxwin.h>3#include<iostream>4#include<stdio.h>5usingnamespacestd;67CRITICAL_SECTIONg_......
  • Python3文件路径/目录获取教程
    一、获取文件路径实现1.1获取当前文件路径importoscurrent_file_path=__file__print(f"current_file_path:{current_file_path}")__file__变量其实有个问题,当文件被是被调用文件时__file__总是文件的绝对路径;但当文件是直接被执行的文件时,__file__并不总是文件的绝对......
  • Python3压缩和解压缩实现
    一、说明压缩和解压缩是日常常用的操作,不管是windows上图形界面的操作,还是linux上用命令来进行压缩解压缩,总的而言都还是比较方便的。但用代码来实现就没做过,近期也得实现代码压缩与解压缩操作,所以就抽时间来研究一下。 二、zip文件压缩和解压缩实现importosimportzipf......
  • 【策略设计模式详解】C/Java/JS/Go/Python/TS不同语言实现
    简介策略模式(StrategyPattern)属于行为型设计模式。将每一个算法封装到具有共同接口的独立类中,根据需要来绑定策略,使得具体实现和策略解耦。当你想使用对象中各种不同的算法变体,使用if...else所带来的复杂和难以维护,可使用策略模式。或者当有许多相同类,它们仅在执行某些行为时......
  • 力扣 228. 汇总区间--python
    给定一个 无重复元素的 有序整数数组nums。返回恰好覆盖数组中所有数字的最小有序区间范围列表 。也就是说,nums的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某个范围但不属于nums的数字x。列表中的每个区间范围[a,b]应该按如下格式输出:"a->b",如果......
  • Vue3实现组件级基类的几种方法
    Vue3的组件有三种代码组织方式纯OptionAPI(不含setup)optionAPI+setup纯setup(即compositionAPI)对于这三种形式,设置基类的方法也略有不同。使用mixins、extendsvue3提供了mixins和extends,但是尝试之后发现这两种方法只支持纯OptionAPI,设置的data会被识别,但是设置的......
  • 使用 for 循环遍历 Python 字典
    #list切片后仍是listlist=['a','b','c','d']print(list[:2]) #['a','b']  结果为listprint(list[:1]) #['a']     结果仍为lists='hello's1=''foriins:ifi=='e......