中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

python中實現單例模式的方法有哪些

發布時間:2021-05-20 17:51:14 來源:億速云 閱讀:206 作者:Leah 欄目:開發技術

這篇文章給大家介紹python中實現單例模式的方法有哪些,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

前言

單例模式(Singleton Pattern),是一種軟件設計模式,是類只能實例化一個對象,

目的是便于外界的訪問,節約系統資源,如果希望系統中 只有一個對象可以訪問,就用單例模式,

顯然單例模式的要點有三個;一是某個類只能有一個實例;二是它必須自行創建這個實例;三是它必須自行向整個系統提供這個實例。

在 Python 中,我們可以用多種方法來實現單例模式:

  • 使用模塊

  • 使用 __new__

  • 使用裝飾器(decorator)

  • 使用元類(metaclass)

概念

簡單說,單例模式(也叫單件模式)的作用就是保證在整個應用程序的生命周期中,任何一個時刻,單例類的實例都只存在一個(當然也可以不存在)

例子:

一臺計算機上可以連好幾個打印機,但是這個計算機上的打印程序只能有一個,這里就可以通過單例模式來避免兩個打印作業同時輸出到打印機中,即在整個的打印過程中我只有一個打印程序的實例。

super(B, self).__init__()是這樣理解的:super(B, self)首先找到B的父類(就是類A),然后把類B的對象self轉換為類A的對象(通過某種方式,一直沒有考究是什么方式,慚愧),然后“被轉換”的類A對象調用自己的__init__函數。考慮到super中只有指明子類的機制,因此,在多繼承的類定義中,通常我們保留使用類似代碼段1的方法。

1. super并不是一個函數,是一個類名,形如super(B, self)事實上調用了super類的初始化函數,
產生了一個super對象;

2. super類的初始化函數并沒有做什么特殊的操作,只是簡單記錄了類類型和具體實例;

3. super(B, self).func的調用并不是用于調用當前類的父類的func函數;

4. Python的多繼承類是通過mro的方式來保證各個父類的函數被逐一調用,而且保證每個父類函數
只調用一次(如果每個類都使用super);

5. 混用super類和非綁定的函數是一個危險行為,這可能導致應該調用的父類函數沒有調用或者一
個父類函數被調用多次。

__new__: 對象的創建,是一個靜態方法,第一個參數是cls。(想想也是,不可能是self,對象還沒創建,哪來的self)

__init__ : 對象的初始化, 是一個實例方法,第一個參數是self。

__new__方法在類定義中不是必須寫的,如果沒定義,默認會調用object.__new__去創建一個對象。如果定義了,就是override,可以custom創建對象的行為。

聰明的讀者可能想到,既然__new__可以custom對象的創建,那我在這里做一下手腳,每次創建對象都返回同一個,那不就是單例模式了嗎?沒錯,就是這樣。可以觀摩《飄逸的python - 單例模式亂彈》

定義單例模式時,因為自定義的__new__重載了父類的__new__,所以要自己顯式調用父類的__new__,即object.__new__(cls, *args, **kwargs),或者用super()。,不然就不是extend原來的實例了,而是替換原來的實例。

代碼

import threading
class Signleton(object):
  def __init__(self):
    print("__init__ method called")
  def __new__(cls):
    print("__new__ method called")
    mutex=threading.Lock()
    mutex.acquire() # 上鎖,防止多線程下出問題
    if not hasattr(cls, 'instance'):
      cls.instance = super(LogSignleton, cls).__new__(cls)
    mutex.release()
    return cls.instance 
if __name__ == '__main__':
obj = Signleton()

輸出結果:

>>> ================================ RESTART ================================
>>>
__new__ method called
__init__ method called
>>>

說明

1.從輸出結果來看,最先調用 __new__ 方法,然后調用__init__方法

2. __new__ 通常用于控制生成一個新實例的過程,它是類級別的方法。

3. __init__ 通常用于初始化一個新實例,控制這個初始化的過程,比如添加一些屬性,做一些額外的操作,發生在類實例被創建完以后。它是實例級別的方法。

方法1

__new__ 在__init__初始化前,就已經實例化對象,可以利用這個方法實現單例模式。

print '----------------------方法1--------------------------' 
#方法1,實現__new__方法 
#并在將一個類的實例綁定到類變量_instance上, 
#如果cls._instance為None說明該類還沒有實例化過,實例化該類,并返回 
#如果cls._instance不為None,直接返回cls._instance 
class Singleton(object): 
  def __new__(cls, *args, **kw): 
    if not hasattr(cls, '_instance'): 
      orig = super(Singleton, cls) 
      cls._instance = orig.__new__(cls, *args, **kw) 
    return cls._instance 
 
class MyClass(Singleton): 
  a = 1 
 
one = MyClass() 
two = MyClass() 
 
two.a = 3 
print one.a 
#3 
#one和two完全相同,可以用id(), ==, is檢測 
print id(one) 
#29097904 
print id(two) 
#29097904 
print one == two 
#True 
print one is two 
#True

方法2

print '----------------------方法2--------------------------' 
#方法2,共享屬性;所謂單例就是所有引用(實例、對象)擁有相同的狀態(屬性)和行為(方法) 
#同一個類的所有實例天然擁有相同的行為(方法), 
#只需要保證同一個類的所有實例具有相同的狀態(屬性)即可 
#所有實例共享屬性的最簡單最直接的方法就是__dict__屬性指向(引用)同一個字典(dict) 
#可參看:http://code.activestate.com/recipes/66531/ 
class Borg(object): 
  _state = {} 
  def __new__(cls, *args, **kw): 
    ob = super(Borg, cls).__new__(cls, *args, **kw) 
    ob.__dict__ = cls._state 
    return ob 
 
class MyClass2(Borg): 
  a = 1 
 
one = MyClass2() 
two = MyClass2() 
 
#one和two是兩個不同的對象,id, ==, is對比結果可看出 
two.a = 3 
print one.a 
#3 
print id(one) 
#28873680 
print id(two) 
#28873712 
print one == two 
#False 
print one is two 
#False 
#但是one和two具有相同的(同一個__dict__屬性),見: 
print id(one.__dict__) 
#30104000 
print id(two.__dict__) 
#30104000

方法3

print '----------------------方法3--------------------------' 
#方法3:本質上是方法1的升級(或者說高級)版 
#使用__metaclass__(元類)的高級python用法 
class Singleton2(type): 
  def __init__(cls, name, bases, dict): 
    super(Singleton2, cls).__init__(name, bases, dict) 
    cls._instance = None 
  def __call__(cls, *args, **kw): 
    if cls._instance is None: 
      cls._instance = super(Singleton2, cls).__call__(*args, **kw) 
    return cls._instance 
 
class MyClass3(object): 
  __metaclass__ = Singleton2 
 
one = MyClass3() 
two = MyClass3() 
 
two.a = 3 
print one.a 
#3 
print id(one) 
#31495472 
print id(two) 
#31495472 
print one == two 
#True 
print one is two 
#True

方法4

print '----------------------方法4--------------------------' 
#方法4:也是方法1的升級(高級)版本, 
#使用裝飾器(decorator), 
#這是一種更pythonic,更elegant的方法, 
#單例類本身根本不知道自己是單例的,因為他本身(自己的代碼)并不是單例的 
def singleton(cls, *args, **kw): 
  instances = {} 
  def _singleton(): 
    if cls not in instances: 
      instances[cls] = cls(*args, **kw) 
    return instances[cls] 
  return _singleton 
 
@singleton 
class MyClass4(object): 
  a = 1 
  def __init__(self, x=0): 
    self.x = x 
 
one = MyClass4() 
two = MyClass4() 
 
two.a = 3 
print one.a 
#3 
print id(one) 
#29660784 
print id(two) 
#29660784 
print one == two 
#True 
print one is two 
#True 
one.x = 1 
print one.x 
#1 
print two.x

單例模式

單例模式(Singleton Pattern)是一種常用的軟件設計模式,該模式的主要目的是確保某一個類只有一個實例存在。當你希望在整個系統中,某個類只能出現一個實例時,單例對象就能派上用場。

比如,某個服務器程序的配置信息存放在一個文件中,客戶端通過一個 AppConfig 的類來讀取配置文件的信息。如果在程序運行期間,有很多地方都需要使用配置文件的內容,也就是說,很多地方都需要創建 AppConfig 對象的實例,這就導致系統中存在多個 AppConfig 的實例對象,而這樣會嚴重浪費內存資源,尤其是在配置文件內容很多的情況下。事實上,類似 AppConfig 這樣的類,我們希望在程序運行期間只存在一個實例對象。

在 Python 中,我們可以用多種方法來實現單例模式:

  • 使用模塊

  • 使用 __new__

  • 使用裝飾器(decorator)

  • 使用元類(metaclass)

使用模塊

其實,Python 的模塊就是天然的單例模式,因為模塊在第一次導入時,會生成 .pyc 文件,當第二次導入時,就會直接加載 .pyc 文件,而不會再次執行模塊代碼。因此,我們只需把相關的函數和數據定義在一個模塊中,就可以獲得一個單例對象了。如果我們真的想要一個單例類,可以考慮這樣做:

# mysingleton.py
class My_Singleton(object):
  def foo(self):
    pass
 
my_singleton = My_Singleton()

將上面的代碼保存在文件 mysingleton.py 中,然后這樣使用:

from mysingleton import my_singleton
my_singleton.foo()

使用 __new__
為了使類只能出現一個實例,我們可以使用 __new__ 來控制實例的創建過程,代碼如下:

class Singleton(object):
  _instance = None
  def __new__(cls, *args, **kw):
    if not cls._instance:
      cls._instance = super(Singleton, cls).__new__(cls, *args, **kw) 
    return cls._instance 
 
class MyClass(Singleton): 
  a = 1

在上面的代碼中,我們將類的實例和一個類變量 _instance 關聯起來,如果 cls._instance 為 None 則創建實例,否則直接返回 cls._instance。

執行情況如下:

>>> one = MyClass()
>>> two = MyClass()
>>> one == two
True
>>> one is two
True
>>> id(one), id(two)
(4303862608, 4303862608)

使用裝飾器

我們知道,裝飾器(decorator)可以動態地修改一個類或函數的功能。這里,我們也可以使用裝飾器來裝飾某個類,使其只能生成一個實例,代碼如下:

from functools import wraps
 
def singleton(cls):
  instances = {}
  @wraps(cls)
  def getinstance(*args, **kw):
    if cls not in instances:
      instances[cls] = cls(*args, **kw)
    return instances[cls]
  return getinstance
 
@singleton
class MyClass(object):
  a = 1

在上面,我們定義了一個裝飾器 singleton,它返回了一個內部函數 getinstance,該函數會判斷某個類是否在字典 instances 中,如果不存在,則會將 cls 作為 key,cls(*args, **kw) 作為 value 存到 instances 中,否則,直接返回 instances[cls]。

使用 metaclass

元類(metaclass)可以控制類的創建過程,它主要做三件事:

  • 攔截類的創建

  • 修改類的定義

  • 返回修改后的類

使用元類實現單例模式的代碼如下:

class Singleton(type):
  _instances = {}
  def __call__(cls, *args, **kwargs):
    if cls not in cls._instances:
      cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
    return cls._instances[cls]
 
# Python2
class MyClass(object):
  __metaclass__ = Singleton
 
# Python3
# class MyClass(metaclass=Singleton):
#  pass

python是什么意思

Python是一種跨平臺的、具有解釋性、編譯性、互動性和面向對象的腳本語言,其最初的設計是用于編寫自動化腳本,隨著版本的不斷更新和新功能的添加,常用于用于開發獨立的項目和大型項目。

關于python中實現單例模式的方法有哪些就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

翼城县| 临城县| 西乌珠穆沁旗| 雷波县| 桂林市| 白城市| 青海省| 三门峡市| 阿尔山市| 原平市| 平南县| 海淀区| 汝城县| 图片| 永定县| 博白县| 全州县| 岐山县| 泾川县| 文安县| 资溪县| 巴彦淖尔市| 抚州市| 连云港市| 哈尔滨市| 靖江市| 朝阳县| 榆社县| 开阳县| 张家港市| 张北县| 丰台区| 鹤峰县| 淮安市| 永胜县| 阿鲁科尔沁旗| 东阳市| 阿坝县| 英超| 九江县| 洪江市|