5

the code below is how i implement singleton with metaclass, and it works well

class Test_MetaClass(type):

    def __init__(cls, name, bases, dict):
        super(Test_MetaClass, cls).__init__(cls, bases, dict)
        cls._instance = None
        print 'Test_MetaClass __init__'

    def __call__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super(Test_MetaClass, cls).__call__(*args, **kwargs)
        print 'Test_MetaClass __call__'
        return cls._instance


class A(object):
    __metaclass__ = Test_MetaClass
    def __init__(self):
        print 'A __init__ triggered'

a = A()
b = A()

output:

Test_MetaClass __init__
A __init__ triggered
Test_MetaClass __call__
Test_MetaClass __call__

my question is why b = A() straight go to Test_MetaClass.__call__ and ignore __init__ ?

Elazar
  • 20,415
  • 4
  • 46
  • 67
limboy
  • 3,879
  • 7
  • 37
  • 53
  • Your metaclass could be simpler. Not an answer so you'll have to deal with comment formatting. `class Singleton(type): cls._instance = None; def __call__(cls, *args, **kwargs): if cls._instance is None: cls._instance = super(Singleton, cls).__call__(*args, **kwargs); return cls._instance;` – agf Aug 02 '11 at 05:55

1 Answers1

2

Isn't that what you wanted? cls._instance isn't None, so it won't execute type.__call__(cls, *args, **kwargs):

>>> type.__call__(A)
A __init__ triggered
<__main__.A object at 0x00BADB30>

It's through this call that A.__new__ and A.__init__ get called to create/initialize a new instance. But for your singleton you only want one instance.

Eryk Sun
  • 33,190
  • 5
  • 92
  • 111