国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 編程 > Python > 正文

python中單例常用的幾種實(shí)現(xiàn)方法總結(jié)

2020-01-04 14:23:07
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

前言

最近這兩天在看自己之前寫的代碼,所以正好把用過(guò)的東西整理一下,單例模式,在日常的代碼工作中也是經(jīng)常被用到,

所以這里把之前用過(guò)的不同方式實(shí)現(xiàn)的單例方式整理一下

什么是單例?

確保某一個(gè)類只有一個(gè)實(shí)例,而且自行實(shí)例化并向整個(gè)系統(tǒng)提供這個(gè)實(shí)例,這個(gè)類稱為單例類,單例模式是一種對(duì)象創(chuàng)建型模式。

那么單例模式有什么用途呢?舉個(gè)常見的單例模式例子,我們平時(shí)使用的電腦上都有一個(gè)回收站,在整個(gè)操作系統(tǒng)中,回收站只能有一個(gè)實(shí)例,整個(gè)系統(tǒng)都使用這個(gè)唯一的實(shí)例,而且回收站自行提供自己的實(shí)例,因此回收站是單例模式的應(yīng)用。

裝飾器的方式

這種方式也是工作中經(jīng)常用的一種,用起來(lái)也比較方便,代碼實(shí)現(xiàn)如下

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

如果我們工作的一個(gè)類需要用單例就通過(guò)類似下面的方式實(shí)現(xiàn)即可:

@Singletonclass A(object): def __init__(self, x):  self.x = x

我個(gè)人還是挺喜歡這種方式的

類的方式實(shí)現(xiàn)

這里其實(shí)有一些問(wèn)題就需要注意了,先看一下可能出現(xiàn)的錯(cuò)誤代碼

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

乍一看這個(gè)類好像已經(jīng)實(shí)現(xiàn)了單例,但是這里有一個(gè)潛在的問(wèn)題,就是如果是多線程的情況,這樣寫就會(huì)有問(wèn)題了,尤其是在當(dāng)前類的初始化對(duì)象里有一些耗時(shí)操作時(shí)候

例如下面代碼:

#! /usr/bin/env python3# .-*- coding:utf-8 .-*-import timeimport threadingimport randomclass 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._instancedef task(arg): obj = Member.instance() print(obj)for i in range(5): t = threading.Thread(target=task, args=[i,]) t.start()

這段代碼的執(zhí)行結(jié)果會(huì)出現(xiàn)實(shí)例化了多個(gè)對(duì)象,導(dǎo)致你寫的單例就沒(méi)起到作用

當(dāng)然自然而然我們會(huì)想起加鎖,通過(guò)鎖來(lái)控制,所以我們將上面代碼進(jìn)行更改:

#! /usr/bin/env python3# .-*- coding:utf-8 .-*-import timeimport threadingimport randomclass 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._instancedef task(): obj = Member.instance() print(obj)for i in range(5): threading.Thread(target=task,).start()

但是上面的代碼還有一個(gè)問(wèn)題,就是當(dāng)我們已經(jīng)實(shí)例化過(guò)之后每次調(diào)用instance都會(huì)去請(qǐng)求鎖,所以這點(diǎn)并不好,所以我們將這部分代碼再次更改:

@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

這樣就很好的實(shí)現(xiàn)一個(gè)可以多線程使用的單例

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)VEVB武林網(wǎng)的支持。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到python教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 房山区| 蛟河市| 喜德县| 容城县| 太白县| 莲花县| 绍兴县| 来凤县| 安福县| 中牟县| 博客| 巧家县| 姜堰市| 赤峰市| 新野县| 大冶市| 建湖县| 盐源县| 尚义县| 安阳市| 新晃| 灵台县| 二连浩特市| 白河县| 镇沅| 古交市| 林周县| 巫溪县| 平江县| 吉水县| 嘉峪关市| 海丰县| 拜泉县| 融水| 白城市| 杭锦旗| 淮南市| 武汉市| 潢川县| 报价| 迁安市|