I recently came across this question.
import Object
class Visitor(Object):
def __init__(self):
super(Visitor,self).__init__()
def visit(self, obj):
pass
def getIsDone(self):
return False
isDone = property(fget =lambda self:self.getIsDone())
I get this error:
TypeError: module.__init__() takes at most 2 arguments (3 given)
and its answer:
class A:pass
print(A) #outputs <class '__main__.A'>
import urllib
print(urllib) #outputs <module 'urllib' from '/usr/lib/python3.2/urllib/__init__.py'>
Your error is happening because Object is a module, not a class. So
your inheritance is screwy.
Change your import statement to:
from Object import ClassName
and your class definition to:
class Visitor(ClassName):
or
change your class definition to:
class Visitor(Object.ClassName):
etc
I'm not really satisfied with this answer as I'm not really sure how I get from that error message to the conclusion that I am accidentally inheriting from a module instead of a class. I was wondering if somebody could elaborate on why this error is occurring and what exactly the arguments being given are? When the python interpreter comes across code like this:
class Employee(Person)
what is happening? What exactly does the answerer mean by my inheritance is screwy? Thanks for any explanations or references to resources.
If you put an object called BaseClass
in the inheritance list, then the interpreter will call this internally:
type(BaseClass).__init__(cls, name_of_subclass, (BaseClass,), dict_of_subclass)
# or simpler
type(BaseClass)(name_of_subclass, (BaseClass,), dict_of_subclass)
You can create a dummy BaseClass to test it
class Meta(object):
def __init__(self, name, base, subcls):
print (self, name, base, subcls)
Base = Meta('','','')
class Test(Base):
prop1="hello"
which outputs:
<__main__.Meta object at 0x7f7471666bd0>
<__main__.Meta object at 0x7f7471666c50> Test (<__main__.Meta object at 0x7f7471666bd0>,) {'__module__': '__main__', 'prop1': 'hello'}
To answer your question: When the interpreter sees class Employee(Person): pass
, the following will happen:
type(Person).__init__(cls, 'Employee', (Person,), {'__module__': '__main__'})
If Person
is a normal class, type(person)
will return type
itself. Then type.__init__
will get called.
If Person
is a module, type(person)
will return the object module
, which has a method __init__
. But this method only takes 2 argument, there you get an error.
import sys
type(sys).__init__(sys,2,3,4)
#Traceback (most recent call last):
# File "testClassInheritance.py", line 11, in <module>
# type(sys).__init__(sys,2,3,4)
#TypeError: module.__init__() takes at most 2 arguments (3 given)
To find out where you've gone wrong, you don't really need to look at the error message in this case, it's pretty clear from the code itself.
import foo
Always means that foo is a module (as opposed to from foo import bar
where bar
can be a module, class, function a variable and so on). This is where naming conventions help us, if PEP8
is followed, then one can easily differentiate between classes and module. The code in your question doesn't follow which is clearly not good for others to understand.
Once you get that you've tried to subclass/inherit a module
the rest is not that tricky.
Most of the modules don't define __init__
which means when you try to access it, it simply tries to find it up in the inheritance chain (if you're really interested in that, you can read upon python inheritance, mro etc, but I suspect that's not what has confused you here.) and finds the builtin class module
which (do import Object;type(Object)
or import os; type(os)
) has a __init__
expecting different arguments than your overridden method. This would have been more tricky to debug if your method has exactly same number of arguments as the above.
The error message does not seem helpful to you because there is no way for python to understand whether you intentionally want to override the module.__init__
or some class's __init__
. Try
import os
help(type(os))