pythonシングルモデル
9588 ワード
シングルモデルSingleton
オンラインでpythonの単一の例のモードを検索して、実現方式は大体いくつかの方式があります.モジュール導入方式 は を使用する.使用装飾器 は、タプル(metaclass) を使用する.オブジェクト指向の一般的な方法(クラス方法)を使用する 変数名を用いて をカバーする.
推奨方法:
「剣の指offer」のSingletonの実現順序で説明します.直接にpythonが単一の例のモードを実現する一番いい方法である网伝の利点:例示的なオブジェクトの方法 である.欠点:しばらくは思っていませんでしたが、 モジュールインポート方式:
実は、Pythonのモジュールは天然の一例モードです.モジュールは初めて導入すると、モジュールコードが生成されます.pycファイルは、2回目に導入されると、直接にロードされます.pycファイルは、モジュールコードを再実行しません.したがって、関連する関数とデータを一つのモジュールに定義するだけで、一つの例のオブジェクトが得られます.
装飾器を使う
オブジェクト指向の一般的な方法を使用する:利点:他の対象言語と似たような方式を使うと、受け入れやすいです. 欠点:実際にはリスクがあり、 ではない.
変数名でカバーする方法:利点:簡単で自然なマルチスレッド を実現する.欠点:レイヤーがはっきりしていないので、継承できません.対象は石の隙間から飛び出してきたようです.とても奇妙です.
この方法については、このように一例を実現してほしいというわけではなく、このような考え方も面白いと思います.以下のように、pythonの柔軟性を強調したいです.ここには、
タプルを使う
元はpythonで複雑で一般的に使われるものが少ないからです.ここではあまり深く追究したくないです.興味のある学生は自分でgoogleを見てもいいです.
まとめ:
pythonはシングルモデルを実現する方法がたくさんありますが、オススメです. 宣言:
私もpython白です.上記の内容に間違いがあれば、ご指摘ください.感謝にたえません.ありがとうございます.
参考資料: pythonの7つの方法で、シングル・モードを実現する .《剣の指のoffer》の面接試験問題2: Pythonにおける一例モードのいくつかの実施形態および最適化`.
オンラインでpythonの単一の例のモードを検索して、実現方式は大体いくつかの方式があります.
__new__
推奨方法:
「剣の指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白です.上記の内容に間違いがあれば、ご指摘ください.感謝にたえません.ありがとうございます.
参考資料: