我有四个不同的班。有一个主基类/父类,两个从父类继承的主类,另一个从这两个主类继承的类。如果我有一个与父类同名但参数数目不同的方法,我会得到一个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,即使它用一个参数调用父类方法。在
这种类型的继承称为"The Diamond Problem"。它本身就是一个话题,所以我将用一个更简单的例子来解释:
C2.check
重写所有C2实例上的C1.check
。因此,当从method
调用self.check(arg)
时,它为C2的实例调用{C2.check
接受两个参数。在如何解决这个问题?重写方法时,不要更改它们的签名(收到的参数的数目和类型以及返回值的类型),否则会有麻烦的。在
[more advanced]使用^{} and ^{} 的函数可以获得更多的自由。在
除此之外,我看到}。那是不对的。
您应该在所有基类上调用该方法(并冒着调用父实现两次的风险,甚至可能就在这里),或者使用^{} 。在
ChildThree.check
调用Child.check
,它调用Parent.check
,但是没有人调用{考虑这一行:
您显式地传入了
^{pr2}$self
。self
这里是对ChildThree
实例的引用。后来,在ChildTwo.method
的主体中:这与我们在这里讨论的
self
相同;self
仍然是ChildThree
实例的引用。在看起来你希望
self
做一些神奇的事情,但它没有-它只是一个普通的老名字。如果要引用ChildTwo
实例,则必须像绑定方法一样调用它。比较和对比:my_child_two.method(arg)
<;“self”通过描述符协议隐式传递ChildTwo.method(self, arg)
<;“自我”就是一切相关问题 更多 >
编程相关推荐