What are the implicit arguments passed to module __init__()?

Viewed 72

Given the following:

ParentModule.py

class ParentClass():
    def __init__(self):
        pass

ChildModule.py

class ChildClass(ParentClass):
    def __init__(self):
        pass

If, in ChildModule, I mistakenly import the parent module and not the parent class, i.e.:

import ParentModule

instead of the correct

from ParentModule import ParentClass

I will get the following error:

TypeError: module.__init__() takes at most 2 arguments (3 given)

So just what are these 3 implicit arguments passed to ParentModule's __init__()? What are the 2 arguments ParentModule.__init__() is expecting?

How does one take advantage of this functionality?

2 Answers

First, the error message is a bit misleading, because it's ignoring the implicit self argument. It should probably say takes at most 3 arguments (4 given), accounting for self.

If you take a look at the help output for the module type:

>>> import sys
>>> help(type(sys))

you'll see the following:

Help on class module in module builtins:

class module(object)
 |  module(name[, doc])
 |  
 |  Create a module object.
 |  ...

So the module type's __init__ is supposed to take up to 3 arguments: self (not listed), name (the module name), and optionally doc (the docstring).


That's not what you're passing it. When you mistakenly do

import ParentModule

class ChildClass(ParentModule)

Python assumes that ParentModule is a class with a weird metaclass and uses type(ParentModule) to find what should be the metaclass. It finds the module type, and calls it with 3 arguments: the name ('ChildClass'), the bases ((ParentModule,)), and the dict of the new class you're trying to create:

type(ParentModule)('ChildClass', (ParentModule,), {'__init__': ..., ...})

This results in a call to the module type's __init__ with 4 arguments (inserting self at the front), and the module type's __init__ doesn't like that, so it throws an error.


For more reading on the details of class creation, see the Python data model documentation on metaclasses.

When you import module, the code will load __init__.py file in module. if you want to utilize init, for example preload modules, you could add code into __init__.py

model/
    __init__.py
    func1.py
    func2.py
Related