方法名相同但参数不同的多重继承会产生TypeE

2024-04-26 23:34:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我有四个不同的班。有一个主基类/父类,两个从父类继承的主类,另一个从这两个主类继承的类。如果我有一个与父类同名但参数数目不同的方法,我会得到一个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)

但是,当我从“ChildThree”中的“check”方法中删除第二个参数时,它似乎可以正常工作:

^{pr2}$

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

我对类/继承相当陌生,所以我不确定为什么一个额外的参数会导致一个TypeError,即使它用一个参数调用父类方法。在


Tags: inpytestselfifdefcheckline
2条回答

这种类型的继承称为"The Diamond Problem"。它本身就是一个话题,所以我将用一个更简单的例子来解释:

class C1(object):
    def check(self, arg):
        return 1

    def method(self, arg):
        return self.check(arg)

class C2(C1):
    def check(self, arg1, arg2):   # this overrides C1.check!
        return x + C1.check(self, arg1)

c2 = C2()
c2.method(55)   # fails

C2.check重写所有C2实例上的C1.check。因此,当从method调用self.check(arg)时,它为C2的实例调用{}。这将失败,因为C2.check接受两个参数。在

如何解决这个问题?重写方法时,不要更改它们的签名(收到的参数的数目和类型以及返回值的类型),否则会有麻烦的。在

[more advanced]使用^{} and ^{}的函数可以获得更多的自由。在


除此之外,我看到ChildThree.check调用Child.check,它调用Parent.check,但是没有人调用{}。那是不对的。 您应该在所有基类上调用该方法(并冒着调用父实现两次的风险,甚至可能就在这里),或者使用^{}。在

考虑这一行:

ChildTwo.method(self, arg)

您显式地传入了selfself这里是对ChildThree实例的引用。后来,在ChildTwo.method的主体中:

^{pr2}$

这与我们在这里讨论的self相同;self仍然是ChildThree实例的引用。在

看起来你希望self做一些神奇的事情,但它没有-它只是一个普通的老名字。如果要引用ChildTwo实例,则必须像绑定方法一样调用它。比较和对比:

  • my_child_two.method(arg)<;“self”通过描述符协议隐式传递
  • ChildTwo.method(self, arg)<;“自我”就是一切

相关问题 更多 >