欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python設(shè)計(jì)模式中單例模式的實(shí)現(xiàn)及在Tornado中的應(yīng)用

 更新時(shí)間:2016年03月02日 18:13:38   作者:Damnever  
這篇文章主要介紹了Python設(shè)計(jì)模式中單例模式的實(shí)現(xiàn)及在Tornado中的應(yīng)用,講解了單例模式用于設(shè)計(jì)Tornado框架中的線程控制方面的相關(guān)問(wèn)題,需要的朋友可以參考下

單例模式的實(shí)現(xiàn)方式
將類實(shí)例綁定到類變量上

class Singleton(object):
  _instance = None

  def __new__(cls, *args):
    if not isinstance(cls._instance, cls):
      cls._instance = super(Singleton, cls).__new__(cls, *args)
    return cls._instance

但是子類在繼承后可以重寫(xiě)__new__以失去單例特性

class D(Singleton):

  def __new__(cls, *args):
    return super(D, cls).__new__(cls, *args)

使用裝飾器實(shí)現(xiàn)

def singleton(_cls):
  inst = {}

  def getinstance(*args, **kwargs):
    if _cls not in inst:
      inst[_cls] = _cls(*args, **kwargs)
    return inst[_cls]
  return getinstance

@singleton
class MyClass(object):
  pass

問(wèn)題是這樣裝飾以后返回的不是類而是函數(shù),當(dāng)然你可以singleton里定義一個(gè)類來(lái)解決問(wèn)題,但這樣就顯得很麻煩了

使用__metaclass__,這個(gè)方式最推薦

class Singleton(type):
  _inst = {}
  
  def __call__(cls, *args, **kwargs):
    if cls not in cls._inst:
      cls._inst[cls] = super(Singleton, cls).__call__(*args)
    return cls._inst[cls]


class MyClass(object):
  __metaclass__ = Singleton


Tornado中的單例模式運(yùn)用
來(lái)看看tornado.IOLoop中的單例模式:

class IOLoop(object):

  @staticmethod
  def instance():
    """Returns a global `IOLoop` instance.

Most applications have a single, global `IOLoop` running on the
main thread. Use this method to get this instance from
another thread. To get the current thread's `IOLoop`, use `current()`.
"""
    if not hasattr(IOLoop, "_instance"):
      with IOLoop._instance_lock:
        if not hasattr(IOLoop, "_instance"):
          # New instance after double check
          IOLoop._instance = IOLoop()
    return IOLoop._instance

為什么這里要double check?來(lái)看個(gè)這里面簡(jiǎn)單的單例模式,先來(lái)看看代碼:

class Singleton(object):

  @staticmathod
  def instance():
    if not hasattr(Singleton, '_instance'):
      Singleton._instance = Singleton()
    return Singleton._instance

在 Python 里,可以在真正的構(gòu)造函數(shù)__new__里做文章:

class Singleton(object):

  def __new__(cls, *args, **kwargs):
    if not hasattr(cls, '_instance'):
      cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
    return cls._instance

這種情況看似還不錯(cuò),但是不能保證在多線程的環(huán)境下仍然好用,看圖:

201632180733229.png (683×463)

出現(xiàn)了多線程之后,這明顯就是行不通的。

1.上鎖使線程同步
上鎖后的代碼:

import threading

class Singleton(object):

  _instance_lock = threading.Lock()
  
  @staticmethod
  def instance():
    with Singleton._instance_lock:
      if not hasattr(Singleton, '_instance'):
        Singleton._instance = Singleton()
    return Singleton._instance

這里確實(shí)是解決了多線程的情況,但是我們只有實(shí)例化的時(shí)候需要上鎖,其它時(shí)候Singleton._instance已經(jīng)存在了,不需要鎖了,但是這時(shí)候其它要獲得Singleton實(shí)例的線程還是必須等待,鎖的存在明顯降低了效率,有性能損耗。

2.全局變量
在 Java/C++ 這些語(yǔ)言里還可以利用全局變量的方式解決上面那種加鎖(同步)帶來(lái)的問(wèn)題:

class Singleton {

  private static Singleton instance = new Singleton();
  
  private Singleton() {}
  
  public static Singleton getInstance() {
    return instance;
  }
  
}

在 Python 里就是這樣了:

class Singleton(object):

  @staticmethod
  def instance():
    return _g_singleton

_g_singleton = Singleton()

# def get_instance():
# return _g_singleton

但是如果這個(gè)類所占的資源較多的話,還沒(méi)有用這個(gè)實(shí)例就已經(jīng)存在了,是非常不劃算的,Python 代碼也略顯丑陋……

所以出現(xiàn)了像tornado.IOLoop.instance()那樣的double check的單例模式了。在多線程的情況下,既沒(méi)有同步(加鎖)帶來(lái)的性能下降,也沒(méi)有全局變量直接實(shí)例化帶來(lái)的資源浪費(fèi)。

3.裝飾器

如果使用裝飾器,那么將會(huì)是這樣:

import functools

def singleton(cls):
  ''' Use class as singleton. '''

  cls.__new_original__ = cls.__new__

  @functools.wraps(cls.__new__)
  def singleton_new(cls, *args, **kw):
    it = cls.__dict__.get('__it__')
    if it is not None:
      return it

    cls.__it__ = it = cls.__new_original__(cls, *args, **kw)
    it.__init_original__(*args, **kw)
    return it

  cls.__new__ = singleton_new
  cls.__init_original__ = cls.__init__
  cls.__init__ = object.__init__

  return cls

#
# Sample use:
#

@singleton
class Foo:
  def __new__(cls):
    cls.x = 10
    return object.__new__(cls)

  def __init__(self):
    assert self.x == 10
    self.x = 15

assert Foo().x == 15
Foo().x = 20
assert Foo().x == 20

def singleton(cls):
  instance = cls()
  instance.__call__ = lambda: instance
  return instance

#
# Sample use
#

@singleton
class Highlander:
  x = 100
  # Of course you can have any attributes or methods you like.

Highlander() is Highlander() is Highlander #=> True
id(Highlander()) == id(Highlander) #=> True
Highlander().x == Highlander.x == 100 #=> True
Highlander.x = 50
Highlander().x == Highlander.x == 50 #=> True

相關(guān)文章

  • Python中使用subprocess庫(kù)創(chuàng)建附加進(jìn)程

    Python中使用subprocess庫(kù)創(chuàng)建附加進(jìn)程

    這篇文章主要介紹了subprocess庫(kù):Python中創(chuàng)建附加進(jìn)程的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-05-05
  • 學(xué)習(xí)python的前途 python掙錢

    學(xué)習(xí)python的前途 python掙錢

    在本文里我們給大家整理了關(guān)于學(xué)習(xí)python的前途以及python掙錢的方法整理,有興趣的朋友們閱讀下。
    2019-02-02
  • Python模擬簡(jiǎn)單電梯調(diào)度算法示例

    Python模擬簡(jiǎn)單電梯調(diào)度算法示例

    這篇文章主要介紹了Python模擬簡(jiǎn)單電梯調(diào)度算法,涉及Python線程、隊(duì)列、時(shí)間延遲等相關(guān)操作技巧,需要的朋友可以參考下
    2018-08-08
  • python flask解析json數(shù)據(jù)不完整的解決方法

    python flask解析json數(shù)據(jù)不完整的解決方法

    這篇文章主要介紹了python flask解析json數(shù)據(jù)不完整的解決方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-05-05
  • Python+PyQt5實(shí)現(xiàn)網(wǎng)口功能測(cè)試詳解

    Python+PyQt5實(shí)現(xiàn)網(wǎng)口功能測(cè)試詳解

    這篇文章主要為大家詳細(xì)介紹了Python+PyQt5實(shí)現(xiàn)網(wǎng)口功能測(cè)試的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-02-02
  • PyTorch實(shí)現(xiàn)FedProx聯(lián)邦學(xué)習(xí)算法

    PyTorch實(shí)現(xiàn)FedProx聯(lián)邦學(xué)習(xí)算法

    這篇文章主要為大家介紹了PyTorch實(shí)現(xiàn)FedProx的聯(lián)邦學(xué)習(xí)算法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • python實(shí)現(xiàn)代理服務(wù)功能實(shí)例

    python實(shí)現(xiàn)代理服務(wù)功能實(shí)例

    本文分析了代理服務(wù)的原理,并使用PYTHON實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的代理服務(wù)功能供大家參考使用
    2013-11-11
  • 淺談Python中的閉包

    淺談Python中的閉包

    簡(jiǎn)單說(shuō),閉包就是根據(jù)不同的配置信息得到不同的結(jié)果。再來(lái)看看專業(yè)的解釋:閉包(Closure)是詞法閉包(Lexical Closure)的簡(jiǎn)稱,是引用了自由變量的函數(shù)。這個(gè)被引用的自由變量將和這個(gè)函數(shù)一同存在,即使已經(jīng)離開(kāi)了創(chuàng)造它的環(huán)境也不例外。
    2015-07-07
  • python神經(jīng)網(wǎng)絡(luò)Keras搭建RFBnet目標(biāo)檢測(cè)平臺(tái)

    python神經(jīng)網(wǎng)絡(luò)Keras搭建RFBnet目標(biāo)檢測(cè)平臺(tái)

    這篇文章主要為大家介紹了python神經(jīng)網(wǎng)絡(luò)Keras搭建RFBnet目標(biāo)檢測(cè)平臺(tái),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • python 基于selectors庫(kù)實(shí)現(xiàn)文件上傳與下載

    python 基于selectors庫(kù)實(shí)現(xiàn)文件上傳與下載

    這篇文章主要介紹了python 基于selectors庫(kù)實(shí)現(xiàn)文件上傳與下載的示例代碼,幫助大家更好的理解和使用python,感興趣的朋友可以了解下
    2020-12-12

最新評(píng)論