2013年9月10日火曜日

Python 2.xと3.xに両対応した継承するだけでSingletonになるクラスを書きました

継承するだけでSingletonになるクラスです。Python 2.xでも3.xでも使用することができます。
getInstance()のような操作は不要です。

>>> from singleton import Singleton
>>> class SubClass(Singleton):
...     pass
...     
... 
>>> sub = SubClass()
>>> sub.value = 1
>>> print(sub.value)
1
>>> SubClass().value
1

本体です。
#!/usr/bin/env python
# -*- coding: utf-8 -*-


class _Singleton(type):
    """
    Python 2.xと3.xの両方をサポートするためには、このように継承しなければならない。

    class SubClass(_Singleton('Singleton', (object, ), {})):
        pass
    """
    __instances = {}

    def __call__(cls):
        if cls not in cls.__instances:
            cls.__instances[cls] = super(_Singleton, cls).__call__()
        return cls.__instances[cls]


# _SingletonをPython 2.xでも3.xでも使えるように継承するのは手間なので、このクラスでラップしている
class Singleton(_Singleton('Singleton', (object, ), {})):
    """
    このクラスを継承するとシングルトンになる。

    class SubClass(_Singleton):
        pass
    """
    pass
テストです。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import unittest2 as unittest
from singleton import Singleton


class TestSingleton(Singleton):
    pass


class AnotherTestSingleton(Singleton):
    pass


class SingletonTest(unittest.TestCase):
    def test_same_instance(self):
        self.assertTrue(TestSingleton() is TestSingleton())

    def test_hold_value(self):
        singleton = TestSingleton()
        singleton.value = "This is value."

        self.assertEqual(singleton.value, TestSingleton().value)

    def test_independent(self):
        singleton = TestSingleton()
        singleton.value = "This is value."

        self.assertFalse(singleton is AnotherTestSingleton())
        self.assertFalse(hasattr(AnotherTestSingleton(), 'value'))


if __name__ == '__main__':
    unittest.main()

Gistにもあります。

0 件のコメント:

コメントを投稿