pythonシングルモデル

9588 ワード

シングルモデルSingleton
オンラインでpythonの単一の例のモードを検索して、実現方式は大体いくつかの方式があります.
  • モジュール導入方式
  • __new__
  • を使用する.
  • 使用装飾器
  • は、タプル(metaclass)
  • を使用する.
  • オブジェクト指向の一般的な方法(クラス方法)を使用する
  • 変数名を用いて
  • をカバーする.
    推奨方法:
    「剣の指offer」のSingletonの実現順序で説明します.直接にpythonが単一の例のモードを実現する一番いい方法である网伝の__new__方式を考えています.直接コードをつけます.
    class Singleton(object):
        __instance = None
        def __new__(cls, *args, **kwargs):
            if not Singleton.__instance:
                Singleton.__instance = super().__new__(cls)
            return Singleton.__instance
    
    #  
    for i in range(5):
        s = Singleton()
        print(s)
      :
    <__main__.singleton object="" at="">
    <__main__.singleton object="" at="">
    <__main__.singleton object="" at="">
    <__main__.singleton object="" at="">
    <__main__.singleton object="" at="">
    
    5回の実装されたSingletonオブジェクトは同じ変数であるが、この方法はシングルスレッドモードのみに適用され、複数のスレッドが同時にif not Singleton.__instance:に入ると、異なるSingletonオブジェクトに戻る可能性がある.
    #  :
    import time
    import threading
    
    class Singleton(object):
        __instance = None
        def __new__(cls, *args, **kwargs):
            if not Singleton.__instance:
                time.sleep(2) #            ,          ,    2  
                Singleton.__instance = super().__new__(cls)
            return Singleton.__instance
    
    def test():
        s = Singleton()
        print('------%s
    ' % s) def main(): t = {} for i in range(5): t[i] = threading.Thread(target=test) t[i].start() for i in range(5): t[i].join() main() : ------<__main__.singleton object="" at=""> ------<__main__.singleton object="" at=""> ------<__main__.singleton object="" at=""> ------<__main__.singleton object="" at=""> ------<__main__.singleton object="" at="">
    5回の実装例が分かるSingletonオブジェクトは、マルチスレッドの場合に、真の単一の例が実現されていないことは確かである.どうすればいいですか?自然に方法があります.引き続き「剣指offer」の考え方に従って、スレッドが占拠している共有資源のところに鍵をかけます.以下のとおりです
    class Singleton(object):
        __lock = threading.Lock() #       
        __instance = None
        def __new__(cls, *args, **kwargs):
            Singleton.__lock.acquire()
            if not Singleton.__instance:
                time.sleep(2) #            ,          ,    2  
                Singleton.__instance = super().__new__(cls)
            Singleton.__lock.release()
            return Singleton.__instance
    #  
      :
    ------<__main__.singleton object="" at="">
    ------<__main__.singleton object="" at="">
    ------<__main__.singleton object="" at="">
    ------<__main__.singleton object="" at="">
    ------<__main__.singleton object="" at="">
    
    以上のように、マルチスレッドの場合、毎回取得されるSingletonオブジェクトは同じ変数であり、ここでは__lockはクラスの中で唯一である必要があり、そうでないと下のロックと解除ロックプロセスが無効になり、またはエラーが発生します.ネット上および「剣指offer」の流れに従って、引き続き最適化します.つまり、Singleton.__lock.acquire()錠をかけて、ロックを解除する過程は時間がかかります.だから、鍵をかける前に、次のように判断します.
    ...
    class Singleton(object):
        __lock = threading.Lock()
        __instance = None
        def __new__(cls, *args, **kwargs):
            if not Singleton.__instance:
                Singleton.__lock.acquire()
                if not Singleton.__instance:
                    time.sleep(2) #            ,          ,    2  
                    Singleton.__instance = super().__new__(cls)
                Singleton.__lock.release()
            return Singleton.__instance
    ...
    
    このように、最初のスレッドだけがifに入ります.つまり、一つのスレッドだけが のプロセスを行い、その後のスレッドは直接に既存の__instanceのインスタンスに戻ります.pythonの対象向け機構は他の言語java C茐などと異なるので、「剣指offer」の後の2つの方法はpythonで実現するのは難しいかもしれません.これでpythonの最初の実施方法Singletonを終了します.しかし、私の実際のテストを経て、pythonの中での過程はそんなに時間がかかりませんでした.分かりません.もしどなたか教えてください.ありがとうございます.テストは以下の通りです
    import time
    import threading
    
    class Singleton(object):
        __lock = threading.Lock()
        __instance = None
        def __new__(cls, *args, **kwargs):
            if not Singleton.__instance:
                Singleton.__lock.acquire()
                if not Singleton.__instance:
                    time.sleep(2) #            ,          ,    2  
                    Singleton.__instance = super().__new__(cls)
                Singleton.__lock.release()
            return Singleton.__instance
    
    def test():
        s = Singleton()
        print('------%s
    ' % s) def main(): start = time.time() t = {} for i in range(5): t[i] = threading.Thread(target=test) t[i].start() for i in range(5): t[i].join() end = time.time() print(end-start) main() # : : ...... 2.285130739212036 if , : 2.279130220413208
    2つの実施形態に対して時間を消費するテストを行ったら、if not Singleton.__instance:で判断した実現方式と判断していない実現方式を作ったのに比べて、そんなに時間がかかりません.前者は後者より時間がかかります.だから、最初のマルチスレッドでの実装を推奨します.
  • 利点:例示的なオブジェクトの方法singleton= Singleton()サブクラスの直接継承も、単一の例
  • である.
  • 欠点:しばらくは思っていませんでしたが、__new__()方法が強すぎて、おすすめできませんでした.ハ
  • モジュールインポート方式:
    実は、Pythonのモジュールは天然の一例モードです.モジュールは初めて導入すると、モジュールコードが生成されます.pycファイルは、2回目に導入されると、直接にロードされます.pycファイルは、モジュールコードを再実行しません.したがって、関連する関数とデータを一つのモジュールに定義するだけで、一つの例のオブジェクトが得られます.
             singleton_moudle.py:
    class Singleton(object):
        #  ...
        data = None
        #   
        def hh(self):
            pass
    
    singleton = Singleton()
    ......
            ,   singleton          
      test.py  
    from singleton_moudle import singleton
    print(singleton)
    
    利点:実現方法は簡単で、しかも天然のマルチスレッドの欠点でもあります.結合性が強く、モジュール導入時に占有空間を生成し、単独の例の継承を実現できません.
    装飾器を使う
    import threading
    
    def singleton(cls):
        __singleton = {}
        def mySingleton(*args, **kwargs):
            if cls not in __singleton:
                __singleton[cls] = cls(*args, **kwargs)
            return __singleton[cls]
        return mySingleton
    
    @singleton
    class A(object):
        data = None
        
        def hh(self):
            print('ggggggg')
    
    
    この方法はすばらしいと言えます.まったくの一例ライブラリです.長所:任意の種類を一例類に飾ります.便利短所:単スレッドにも適用されます.もちろんロックをかけることでマルチスレッドを実現することができます.これもおすすめの方法です.
    オブジェクト指向の一般的な方法を使用する:@staticmethod@classmethod
    class Singleton(object):
        __instance = None
        __lock = threading.Lock()
        
        def __init__(self):
            raise SyntaxError('can not instance, please use get_instance')
            
        @classmethod
        def get_instance(cls):
            Singleton.__lock.acquire()
            if not Singleton.__instance:
                time.sleep(2)
                Singleton.__instance = object.__new__(cls)
            Singleton.__lock.release()
            return Singleton.__instance
    
    t = []
    def test():
        singleton = Singleton.get_instance()
        print(str(singleton)+'\r
    ') print('------------------start') for i in range(5): t.append(threading.Thread(target=test)) t[i].start() for i in t: i.join() print('------------------end')
    クラス__init__の方法において、手動で異常を投げ、従来の方法を用いてインスタンスを生成することができないことを示したが、クラス方法、または静的方法get_instanceを使用して、一例を取得した.@staticmethodを使用する@classmethodは、Javaにおける単一の例のモードと同様である.ここでは@classmethodで装飾された方法のみが実現され、@staticmethodの方法も同様である.参照ファイルpythonの7つのパターンを実装する方法を参照してください.具体的なコードを確認してください.
  • 利点:他の対象言語と似たような方式を使うと、受け入れやすいです.
  • 欠点:実際にはリスクがあり、s = Singleton()はエラーを報告するが、実際のsは確かにSingletonの例であり、厳密な意味での単一例
  • ではない.
    変数名でカバーする方法: , __call__
    class Singleton(object):
        def hh(self):
            print('hhh')
            
        def __call__(self):
            return self
    
    Singleton = Singleton()
    s1 = Singleton()
    s2 = Singleton()
    print(s1)
    print(s2)
    
    まず、Singleton を作成し、Singleton にオブジェクトを割り当て、このときSingletonはもはやクラスを指すのではなく、具体的な例示的なオブジェクトを指す.Singleton()を呼び出した後、オブジェクトの__call__方法を書き換えるので、直接にオブジェクト自体に戻る.この方法も独特です.簡単ですが、勧められません.
  • 利点:簡単で自然なマルチスレッド
  • を実現する.
  • 欠点:レイヤーがはっきりしていないので、継承できません.対象は石の隙間から飛び出してきたようです.とても奇妙です.
    この方法については、このように一例を実現してほしいというわけではなく、このような考え方も面白いと思います.以下のように、pythonの柔軟性を強調したいです.ここには、python オブジェクトが関数のように実行できるかどうかの知識があります.__call__、すなわち __call__ , 。の実際のクラスが実装されているかどうかを見ると、オブジェクトを実装するのもクラスを呼び出した__call__の方法である.特に、ここでは、オブジェクトの__call__方法をクラスの__call__ではなく修正した方法であるので、第1のステップSingleton= Singleton()は、実際にSingletonオブジェクトの一例を返したが、a=Singleton()を再度呼び出すと、オブジェクトの__call__方法を呼び出して直接にオブジェクト自体に戻る.このように一例を実現しました.もし分からないなら、私のもう一つの文章を見てください.
    タプルを使う
    元はpythonで複雑で一般的に使われるものが少ないからです.ここではあまり深く追究したくないです.興味のある学生は自分でgoogleを見てもいいです.
    まとめ:
    pythonはシングルモデルを実現する方法がたくさんありますが、オススメです.
  • __new__
  • python ( )
  • python , __call__
  • 宣言:
    私もpython白です.上記の内容に間違いがあれば、ご指摘ください.感謝にたえません.ありがとうございます.
    参考資料:
  • pythonの7つの方法で、シングル・モードを実現する
  • .
  • 《剣の指のoffer》の面接試験問題2:
  • Pythonにおける一例モードのいくつかの実施形態および最適化`.