3

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?

3
  • I can't reproduce. Are both modules in the same directory? The only error I get is: NameError: name 'ParentClass' is not defined. Commented Oct 5, 2017 at 17:47
  • Yeah, the ParentClass and ParentModule most likely had the same name in the real code, or the real code had class ChildClass(ParentModule) instead of class ChildClass(ParentClass). Commented Oct 5, 2017 at 17:50
  • @ChristianDean: Yes, the real module/class names would be Parent.Parent and Child.Child, but I felt using that terminology didn't clarify the problem. Feel free to edit the question if you think it would be clearer that way. Commented Oct 6, 2017 at 17:27

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Excellent work! I should have thought to run help() on the module object.
0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.