Pythonの単例オブジェクトの応用
8317 ワード
今日は単例オブジェクトの使用についてお話しします.
単一オブジェクトモード
単一のオブジェクトモードは、クラスにインスタンス化されたオブジェクトが1つしか存在しないことを保証する一般的なソフトウェア設計モードです.この単一のモードは、プログラム全体に1つのクラスに1つのインスタンスしかないことを望む場合に使用できます.
単一モードの実現方法
使用__new__方法
使用__new__メソッドはクラスを一度だけインスタンス化できることを制限し,直接次のメソッドで定義すればよい.
このクラスを初めてオブジェクトにインスタンス化すると、クラス変数_Instnceは新しいオブジェクトとして割り当てられ、再びインスタンス化されるとcls.instanceは値があり、新しいオブジェクトは再インスタンス化されません.idで効果を判定できます
すなわち,それぞれインスタンス化されたaとbは実は1つのオブジェクトである.
モジュールの使用
Pythonのモジュールインポートは天然の単例モードです.モジュールは最初のインポート時に.pycファイルを生成し、2回目のインポート時にpycファイルから先にインポートしたかどうかを探します.以前にこのモジュールをインポートしたことがあれば、インポートのプロセスは実行されません.したがって、モジュール内で必要なオブジェクトをインスタンス化して必要なスクリプトにインポートするのが、単一のオブジェクトです.スクリプトファイルにクラスを定義し、このクラスをインスタンス化しました.
では、別のスクリプトでは、このインスタンス化されたオブジェクトをインポートします.
このオブジェクトaは1回しかインポートできないため、1つのプログラムが多くのスクリプトファイルから構成されている場合、1つのファイルがこのオブジェクトaをインポートしている限り、このaはどのスクリプトでインポートされても実際には1つのオブジェクトであり、名前が変更されても
または複数のpyスクリプトがあります
この変数aを呼び出すファイルがあります
もう一つのファイルがこのfunをインポートしました
最終運行の結論はどうなりますか?
したがって、この2つのスクリプトにインポートされたオブジェクトの1つが単一のオブジェクトです.ただし、クラスをインポートした後にスクリプトでインスタンス化するだけでは、単一の変数ではありません.
上記の例では、aとbは一般的なインスタンス化された2つのオブジェクトである.
アクセサリーを使う
これは大まかに見ればよい,主要な知識点としない
もう1つの方法はmetaclassメタクラスを使用することですが、マルチスレッド環境で問題が発生する場合があります.ここでは先に説明しません.
単一オブジェクトモード
単一のオブジェクトモードは、クラスにインスタンス化されたオブジェクトが1つしか存在しないことを保証する一般的なソフトウェア設計モードです.この単一のモードは、プログラム全体に1つのクラスに1つのインスタンスしかないことを望む場合に使用できます.
単一モードの実現方法
使用__new__方法
使用__new__メソッドはクラスを一度だけインスタンス化できることを制限し,直接次のメソッドで定義すればよい.
class Singleton(object):
_instance = None
def __new__(cls,*args,**kwargs):
if not cls._instance:
cls._instance = super(Singleton,cls).__new__(cls,*args,**kwargs)
return cls._instance
このクラスを初めてオブジェクトにインスタンス化すると、クラス変数_Instnceは新しいオブジェクトとして割り当てられ、再びインスタンス化されるとcls.instanceは値があり、新しいオブジェクトは再インスタンス化されません.idで効果を判定できます
a = Singleton()
b = Singleton()
print(id(a))
print(id(b))
######## ########
139968970404024
139968970404024
すなわち,それぞれインスタンス化されたaとbは実は1つのオブジェクトである.
モジュールの使用
Pythonのモジュールインポートは天然の単例モードです.モジュールは最初のインポート時に.pycファイルを生成し、2回目のインポート時にpycファイルから先にインポートしたかどうかを探します.以前にこのモジュールをインポートしたことがあれば、インポートのプロセスは実行されません.したがって、モジュール内で必要なオブジェクトをインスタンス化して必要なスクリプトにインポートするのが、単一のオブジェクトです.スクリプトファイルにクラスを定義し、このクラスをインスタンス化しました.
#mysingleton.py
class Animal(object):
def run(self):
print('running...')
a = Animal()
では、別のスクリプトでは、このインスタンス化されたオブジェクトをインポートします.
#main.py
from mysingleton import a
a.run()
このオブジェクトaは1回しかインポートできないため、1つのプログラムが多くのスクリプトファイルから構成されている場合、1つのファイルがこのオブジェクトaをインポートしている限り、このaはどのスクリプトでインポートされても実際には1つのオブジェクトであり、名前が変更されても
#main.py
from mysingleton import a as a1
print('a1',id(a1))
from mysingleton import a as a2
print('a2',id(a2))
########## ##########
a1 140212539471856
a2 140212539471856
または複数のpyスクリプトがあります
#mysingleton.py
class Animal(object):
def run(self):
print('running...')
a = Animal()
この変数aを呼び出すファイルがあります
#funcs.py
from mysingleton import a
def fun():
print('in fun a:',id(a))
もう一つのファイルがこのfunをインポートしました
#main.py
from mysingleton import a
import funcs
funcs.fun()
print('in main a',id(a))
最終運行の結論はどうなりますか?
########## ##########
in fun a: 139630131360320
in main a 139630131360320
したがって、この2つのスクリプトにインポートされたオブジェクトの1つが単一のオブジェクトです.ただし、クラスをインポートした後にスクリプトでインスタンス化するだけでは、単一の変数ではありません.
#main.py
from mysingleton import Animal
a = Animal()
b = Animal()
print('a',id(a))
print('b',id(b))
上記の例では、aとbは一般的なインスタンス化された2つのオブジェクトである.
アクセサリーを使う
これは大まかに見ればよい,主要な知識点としない
def Singleton(cls):
_instance = {}
def _singleton(*args,**kwargs):
if cls not in _instance:
_instance[cls] = cls(*args,**kwargs)
return _instance[cls]
return _singleton
@Singleton
class A(object):
def fun(self):
pass
a = A()
b = A()
print('a',id(a))
print('b',id(b))
もう1つの方法はmetaclassメタクラスを使用することですが、マルチスレッド環境で問題が発生する場合があります.ここでは先に説明しません.