PyNoob PyNoob - 2 months ago 17
Python Question

Multiple Inheritance With Same Method Names but Different Arguments Creates TypeError

I have a four distinct classes. There is a main base/parent class, two main classes that inherit from this parent class, and another class that inherits from both of these main classes. If I have a method with the same name but a different number of arguments as a parent class, I get a TypeError.

# Example

class Parent(object):
def check(self, arg):
tmp = {
'one': False,
'two': False
}

try:
if 'one' in arg:
tmp['one'] = True

if 'two' in arg:
tmp['two'] = True
except TypeError:
pass

return tmp

class Child(Parent):
def check(self, arg):
return Parent.check(self, arg)['one']

def method(self, arg):
if self.check(arg):
print 'One!'

class ChildTwo(Parent):
def check(self, arg):
return Parent.check(self, arg)['two']

def method(self, arg):
if self.check(arg):
print 'Two!'

class ChildThree(Child, ChildTwo):
def check(self, arg, arg2):
print arg2
return Child.check(self, arg)

def method(self, arg):
if self.check(arg, 'test'):
print 'One!'

ChildTwo.method(self, arg)

test = ChildThree()
test = test.method('one and two')



runfile('untitled6.py', wdir='./Documents')

test

One!

Traceback (most recent call last):

File "< stdin >", line 1, in < module >

File "C:\Users\py\AppData\Local\Continuum\Anaconda2\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 714, in runfile

execfile(filename, namespace)

File "C:\Users\py\AppData\Local\Continuum\Anaconda2\lib\site-packages\spyderlib\widgets\externalshell\sitecustomize.py", line 74, in execfile

exec(compile(scripttext, filename, 'exec'), glob, loc)

File "untitled6.py", line 49, in

test = test.method('one and two')

File "untitled6.py", line 46, in method

ChildTwo.method(self, arg)

File "untitled6.py", line 34, in method

if self.check(arg):

TypeError: check() takes exactly 3 arguments (2 given)


However, when I remove the second argument from the 'check' method in 'ChildThree', it seems to work fine:

class ChildThree(Child, ChildTwo):
def check(self, arg):
return Child.check(self, arg)

def method(self, arg):
if self.check(arg):
print 'One!'

ChildTwo.method(self, arg)



runfile('untitled6.py', wdir='./Documents')

One!

Two!


I am fairly new to classes/inheritance, so I am not sure why an extra argument causes a TypeError even though it calls the parent class method with a single argument.

wim wim
Answer

Consider this line:

ChildTwo.method(self, arg)

You passed in self explicitly. self here is a reference to a ChildThree instance. Later, in the body of ChildTwo.method:

if self.check(arg):

It's the same self we're talking about here; self is still a reference on your ChildThree instance.

It looks like you expected self to do something magical, but it doesn't - it's just a plain old name. For it to refer to a ChildTwo instance it would have had to be called like a bound method. Compare and contrast:

  • my_child_two.method(arg) <-- "self" gets passed implicitly by descriptor protocol
  • ChildTwo.method(self, arg) <-- "self" is just whatever it is