Java だったら、private コンストラクタにした final クラスで synchronized の static メソッドでインスタンス取得する
お決まりの実装だけど、Python はいくつか方法がある。
getInstance() というメソッドでインスタンス取得させる方法
# -*- coding: utf-8 -*- class MyClass: _instance = None @staticmethod def getInstance(): if MyClass._instance == None: MyClass() return MyClass._instance def __init__(self): if MyClass._instance != None: raise Exception("This is not Singleton !!") else: MyClass._instance = self def setParam(self, p): self.p = p pass def getParam(self): return self.p
インスタンス取得、a も b も同じ
a = MyClass.getInstance() b = MyClass.getInstance()
これなら、 MyClass() と実行しても、Exception("This is not Singleton !!") になる。
Python の通常のインスタンス生成でも、シングルトンにする方法
つまり、MyClass() で生成するインスタンスがシングルトンになり、
一見シングルトンなのかどうか判りづらい方法
class MyClass(): p = None def __new__(self, *args, **kargs): if not hasattr(self, "_instance"): self._instance = super().__new__(self) return self._instance def setParam(self, p): self.p = p pass def getParam(self): return self.p
a = MyClass() b = MyClass()
継承で書く!
singleton.py
class Singleton(): _instance = None def __new__(self, *args, **kargs): if self._instance == None: self._instance = super(Singleton, self).__new__(self) return self._instance
from singleton import Singleton class MyClass(Singleton): p = None def setParam(self, p): self.p = p pass def getParam(self): return self.p
デコレーターで書く!
utility.py
def singleton(cls): instances = {} def getinstance(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return getinstance
@singleton をクラス宣言に書く
from utility import singleton @singleton class MyClass(): p = None def setParam(self, p): self.p = p pass def getParam(self): return self.p
Java に慣れしたんだ者にとって、専用インスタンスメソッド getInstance() が馴染むけど、
Pythonは、コンストラクタの引数を拡張できる方が良いのかな。