0

Take a look at the following example

class Base(type):
    def __init__(cls, name, bases, dict_):
        print 'Base.__init__() with cls %s, name %s...' % (cls, name, )
        type.__init__(cls, name, bases, dict_)

M = Base('M', (object,), {})

class D1(Base):
    pass

class D2(M):
    pass

The output is

Base.__init__() with cls <class '__main__.M'>, name M...
Base.__init__() with cls <class '__main__.D2'>, name D2...

I feel so puzzled about the result,

  1. Why Base.__init__ be invoked for D2, even we have not creat an instance of D2?
  2. Since Base.__init__ be invoked for D2, why D1 not?
poke
  • 369,085
  • 72
  • 557
  • 602
Jacky1205
  • 3,273
  • 3
  • 22
  • 44

1 Answers1

2

Base.__init__ is called the first time when you do:

M = Base('M', (object,), {})

You're creating an instance of Base, so its __init__ method gets called, nothing surprising.

It is called the second time when creating D2 because creating a class calls the __init__ method of the metaclass (yep, class of the class) which is Base; D2 is an instance of Base.

It is not called for D1 since D1 is a subtype/subclass of Base and not an instance of it.

Notice what happens when you make Base the metaclass of D1 instead of its superclass:

class D1(object):
    __metaclass__ = Base
    pass

# Base.__init__() with cls <class 'D1'>, name D1...
Moses Koledoye
  • 77,341
  • 8
  • 133
  • 139
  • I am not familiar with how does `metaclass` work. So I still feel puzzled why `Base.__init__` is called when D2 is an instance of `Base`; even after reading http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python, because `__metaclass__` is not used here. – Jacky1205 Apr 21 '17 at 16:10
  • Another issue: does the position of `__metaclass__` matters? – Jacky1205 Apr 21 '17 at 16:16
  • [The basic principle of the __metaclass__](http://jfine-python-classes.readthedocs.io/en/latest/metaclass-attribute.html#the-basic-principle-of-the-metaclass) – Moses Koledoye Apr 21 '17 at 16:20