激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

腳本之家,腳本語言編程技術(shù)及教程分享平臺(tái)!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Python - Python設(shè)計(jì)模式中單例模式的實(shí)現(xiàn)及在Tornado中的應(yīng)用

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

2020-08-15 12:00Damnever Python

這篇文章主要介紹了Python設(shè)計(jì)模式中單例模式的實(shí)現(xiàn)及在Tornado中的應(yīng)用,講解了單例模式用于設(shè)計(jì)Tornado框架中的線程控制方面的相關(guān)問題,需要的朋友可以參考下

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

?
1
2
3
4
5
6
7
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

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

?
1
2
3
4
class D(Singleton):
 
  def __new__(cls, *args):
    return super(D, cls).__new__(cls, *args)

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

?
1
2
3
4
5
6
7
8
9
10
11
12
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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
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)用
來看看tornado.IOLoop中的單例模式:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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?來看個(gè)這里面簡(jiǎn)單的單例模式,先來看看代碼:

?
1
2
3
4
5
6
7
class Singleton(object):
 
  @staticmathod
  def instance():
    if not hasattr(Singleton, '_instance'):
      Singleton._instance = Singleton()
    return Singleton._instance

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

?
1
2
3
4
5
6
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)境下仍然好用,看圖:

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

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

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

?
1
2
3
4
5
6
7
8
9
10
11
12
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++ 這些語言里還可以利用全局變量的方式解決上面那種加鎖(同步)帶來的問題:

?
1
2
3
4
5
6
7
8
9
10
11
class Singleton {
 
  private static Singleton instance = new Singleton();
  
  private Singleton() {}
  
  public static Singleton getInstance() {
    return instance;
  }
  
}

在 Python 里就是這樣了:

?
1
2
3
4
5
6
7
8
9
10
class Singleton(object):
 
  @staticmethod
  def instance():
    return _g_singleton
 
_g_singleton = Singleton()
 
# def get_instance():
# return _g_singleton

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

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

3.裝飾器

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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

 

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美精品一二三区 | 综合精品久久 | 精品国产一区二区久久 | 免费人成在线播放 | 久久金品 | 国产在线精品一区二区夜色 | 精品国产91久久久久久浪潮蜜月 | 成人三级电影在线 | 日韩精品中文字幕在线播放 | 人人玩人人爽 | 一区在线免费视频 | 欧美视频国产 | 91看片在线播放 | 999久久久精品 | 亚洲午夜在线 | 日韩欧美精品中文字幕 | 亚洲av毛片在线观看 | 男男啪羞羞视频网站 | 91专区在线观看 | 草操视频 | 欧美一级成人 | 欧美在线观看视频一区二区 | 一级一级一级一级毛片 | 99最新网址 | 亚洲av一级毛片特黄大片 | 国产porn在线| 色交视频 | 久久久新 | 久久久久久久久久久久久久久伊免 | 成人毛片一区二区三区 | 2019中文字幕在线播放 | 精品国产91久久久久久浪潮蜜月 | 免费网站看v片在线a | 久久久久久久一区 | 美女一级视频 | 97中文| 久久精品一区二区三区国产主播 | 色人阁导航 | 国产在线看一区 | 一级在线观看 | 亚洲国产精品一区二区三区 |