据我所知,在Python中,父类的方法被覆盖。 因此,默认情况下所有类方法都是虚拟的,如下面的代码所示。
class Parent(object):
def Method1(self):
print 'FOO'
class Child(Parent):
def Method1(self):
print 'BAR'
myInstance = Child()
#Overridden method is called
myInstance.Method1() # BAR
#Is it possible to do the following?
myInstance.{something} # FOO
问题:
是否可以从子类的实例Parent.Method1()
调用父方法myInstance
?
是否可以通过具有相同名称的方法覆盖def Parent.Method1(self)
而不是,但是有一些不同的参数集def Child.Method1(self,x,y)
?
答案 0 :(得分:2)
通过super()
函数搜索MRO中的下一个方法(方法解析顺序)来调用父方法:
class Child(BaseClass):
def Method1(self):
print 'BAR'
super(Child, self).Method1() # will call BaseClass.Method1
其中self
是实例引用,因此super(type(myInstance), myInstance).Method1()
将从方法外部实现相同的功能。
或者您可以访问类上的未绑定方法,并明确传入实例;你也可以在方法之外做到这一点:
BaseClass.Method1(myInstance)
因为现在您直接在类上引用了method属性,并将该实例作为显式self
传递给该方法;你可以在self
那里的方法中使用Child
。
通过名称查找Python属性(方法也是属性),这样的查找通过实例搜索,然后搜索实例的类,然后搜索每个父类,直到找到匹配为止;方法的签名在这里没有发挥作用。
您仍然可以使用关键字参数覆盖子类中的方法,更改签名,但使用父方法保持兼容:
class Child(BaseClass):
def Method1(self, x=None, y=None):
if x is None and y is None:
# arguments left at defaults, call base method
return super(Child, self).Method1()
print 'BAR: {} and {}'.format(x, y)
现在,如果你在没有参数的情况下调用myInstance.Method1()
,则会调用BaseClass.Method1()
方法,传入参数,而是发生其他事情。
答案 1 :(得分:1)
是否可以从中调用父方法Parent.Method1() 实例是子类的myInstance?
您可以直接调用该方法,并将您的实例作为第一个参数传递:
>>> class A(object):
... def foo(self):
... print 'foo'
...
>>> class B(A):
... def foo(self):
... print 'bar'
...
>>> b = B()
>>> A.foo(b)
foo
是否可以使def Parent.Method1(self)不被覆盖 通过具有相同名称的方法,但是一些不同的参数集 def Child.Method1(self,x,y)?
是的,您使用super并直接调用父方法:
>>> class A(object):
... def foo(self, bar='bar'):
... print bar
...
>>> class B(A):
... def foo(self):
... super(B, self).foo(bar='foo')
...
>>> B().foo()
foo
>>> A().foo()
bar
答案 2 :(得分:1)
除了使用super
之外,还有一些绕过MRO的显式选项:
# Explicitly call Baseclass.Method1, passing your instance as the argument
BaseClass.Method1(myInstance)
# Call Method1 on the (first) base class of the instance.
# This is ugly; don't actually write code like this
# x.__class__.__bases__[0] is just another way to get a reference
# to BaseClass; otherwise, this is identical to the previous option,
# hence the need to repeat myInstance
myInstance.__class__.__bases__[0].Method1(myInstance)