PythonでSingletonクラスを実装!継承して利用する方法

PythonでSingleton

プログラムの実行時に、あるクラスのインスタンスが必ず1つになるような実装方式をシングルトン(Singleton)パターンと言います。

Singletonパターンは、理解が容易でありよく利用されているデザインパターンです。

Pythonでシングルトンを実現する方法を紹介します!

この記事ではSingletonクラスを実装し、Singletonクラスを継承したクラスがSingletonパターンになる方法を紹介します!

Sigletonクラスの実装

早速ですが、基礎となるSingletonクラスです。

class Singleton(object): _instance = None def __new__(cls, *args, **kwargs): if not isinstance(cls._instance, cls): cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs) # else以下は、子クラスの__init__を一度しか実行させなくする else: def init_pass(self, *args, **kwargs): pass cls.__init__ = init_pass return cls._instance

一般的には、__new__関数でインスタンスを返しますが、上記ではすでにインスタンスが存在する場合は新しいインスタンスを作成せずに、過去に作成したインスタンスを返すようにしています。

また、すでにインスタンスが存在する場合(elseの処理)、__init__関数の処理を上書きし、なにも処理をさせなくさせています。

これは、子クラスでの__init__関数の実行を1回に限定させるためです。(ここは好みで消したりしても良いです。)

newinitの違い

Pythonでインスタンスを作成する際には__new__()__init__()が呼ばれます。

Pythonのドキュメントに記載ありますが、この二つの違いは__new__はインスタンスを作成し、__init__は作成されたインスタンスをカスタマイズ(インスタンス変数の定義など)する関数であるというところです。

かなり大雑把な説明ではありますが、違いを理解する上では上記で十分かと思います。

Singletonクラスを継承して利用する

上記で作成したSingletonクラスを継承してりようしましょう。

class Singleton(object): # 上記のため省略
class SingletonChild(Singleton): def __init__(self): print('call __init__ on SingletonChild') self._var = 'var' @property def get_var(self): return self._var
singleton1 = SingletonChild()
singleton2 = SingletonChild()
print(singleton1)
print(singleton2)
print(SingletonChild().get_var)

こちらを実行すると、下記の実行結果が得られます。

$ python singleton_child.py
call __init__ on SingletonChild
<__main__.SingletonChild object at 0x7f45e5a51460>
<__main__.SingletonChild object at 0x7f45e5a51460>
var

singleton1とsingleton2のインスタンスで、同じアドレス(0x7f45e5a51460)を参照していることが確認できます。

また、”call __init__ on SingletonChild”が一度しか呼び出されておらず、初期化が一度しか実行されていないことも確認できます。

まとめ

PythonでSingletonパターンを実装する方法を紹介しました。

Singletonは理解が簡単なデザインパターンです。

ただ、使いどころが誤解されやすく、単純なグローバル変数として利用されていることも多々あります。

適切に使えれば非常に便利なので、使いこなしていきたいものです。