chikuchikugonzalezの雑記帳

趣味とか日記とかメモとか(∩゚д゚)

Pythonでシングルトン

基本的にPythonista見習いなので、とりあえずPythonでやってみたい衝動があります。
それでここ最近メタプログラミングとかいうのに目覚めたので、メタクラスを使ってちょいちょい遊びました。

で、手始めにシングルトンオブジェクトをあれやこれや先人の知恵を借りつつメタクラスで実装とかしてみた*1

基本は__new__で既存オブジェクトを返そうかと思ったのですが、それやったら__init__が何度も呼ばれるという不具合発生 (そりゃそうだ)
で、解決策。

そうだ、__call__を使おう

てなわけでコード的にはこんなの出ました

class SingletonType(type):
	def __call__(cls, *args, **kwargs):
		instance = None
		clshash = str(hash(cls))
		if not hasattr(cls, '__instances__'):
			cls.__instances__ = {}
		if not clshash in cls.__instances__:
			instance = type.__call__(cls, *args, **kwargs)
			cls.__instances__[clshash] = instance
		else:
			instance = cls.__instances__[clshash]
		return instance

そして次のようにクラスのmetaclassパラメータにこいつを指定する

class Singleton(metaclass = sdl.Single
	pass

obj1 = Singleton()
obj2 = Singleton()
print(obj1)		# <__main__.Singleton object at 0x027CF830>
print(obj2)		# <__main__.Singleton object at 0x027CF830>

*1:ところでメタクラスの書き方って2.xと3.xで変わりました?