Python:如何继承和覆盖

时间:2010-05-16 09:17:03

标签: python inheritance override

考虑这种情况:

我得到一个A类型的对象,其函数为f。即:

class A:
   def f(self):
      print 'in f'
   def h(self):
      print 'in h'

我得到了这个类的一个实例,但我想覆盖f函数,但保存A的其余功能。所以我的想法是那种:

class B(A):
     def __init__(self, a):
        #something here
     ....

     def f(self):
         print 'in B->f'

,用法是:

def main(a):
   b = B(a)
   b.f()   #prints "in B->f"
   b.h()   #print "in h"

我想要的是一种复制构造函数,它获取当前类(A)的父级并返回此类的实例(B)。

你怎么做这样的事情? __init__方法看起来如何?

注意:此帖子已由原始海报编辑,以纳入下面建议的更改,这就是为什么有些建议看起来多余或不正确。

3 个答案:

答案 0 :(得分:11)

如何构建子类B的对象“基于”类A之一“完全取决于后者如何保持状态,如果有的话,你如何最好到达那个州并复制它。在您的示例中,A的实例是无状态的,因此您需要在B的{​​{1}}中完成任何工作。在一个更典型的例子中,请说:

'__init__'

状态将位于两个实例属性class A(object): def __init__(self): self._x = 23 self._y = 45 def f(self): print 'in f,', self._x def h(self): print 'in h,', self._y _x中,因此您需要复制这些属性:

_y

这是最常见和最普通的方法,子类接受并直接在超类上实现其状态依赖 - 它非常简单和线性。

您通常在class B(A): def __init__(self, a): self._x = a._x self._y = a._y def f(self): print 'in B->f,', self._x 的{​​{1}}中查找A的实例状态方面,因为大多数正常,直接的Python代码在初始化时建立实例状态(属性可能< / em>可以在以后添加和删除,甚至可以从类的正文以外的代码添加和删除,但这并不常见,通常不可取。)

可以添加一些“魔术”(基于内省的编程),例如...:

A

getstate是类可以定义的特殊方法 - 如果它们这样做,则使用它(例如通过pickle)来“获取其实例的状态”以进行序列化(否则,实例的{{1}被视为实例的“状态”)。它可能返回一个字典(在这种情况下'__init__'调用更新class B1(A): def __init__(self, a): try: s = a.__getstate__() except AttributeError: s = a.__dict__ try: self.__setstate__(s) except AttributeError: self.__dict__.update(s) 的状态),但如果该类还定义了接受它的__dict__,它也可能返回任何其他内容(所以此代码首先尝试该路由,然后再回到更新可能性)。请注意,在这个用例中,一个或两个特殊方法都将继承自.update - 我不会在self中定义/覆盖它们(除非有更微妙的目标可以实现当然; - )。

使用这四行“魔法”代替我最初建议的简单作业是否值得?大多数情况下,不简单是优选的。但是如果__setstate__做了什么特别的事情或受外部代码改变其状态的影响,那么这个解决方案可以更强大和更通用(这就是你通过接受它的复杂性而购买的东西)。因此,您必须知道后一种情况是否适用(然后是“寻找特殊状态相关方法的大枪”),或者A及其实例是“非常正常的香草”,其中我强烈建议选择简单和清晰。

答案 1 :(得分:5)

试试这个:

class A:
  def f(self):
    print("in f")

  def h(self):
    print("in h")

class B(A):
  def f(self):
    print("in B:f")

def test(x):
  x.f()
  x.h()

test(A())
test(B())

注意,我正在使用Python 3,这是print在括号中取参数的原因。

输出:

in f
in h
in B:f
in h

答案 2 :(得分:1)

您需要将self参数放入python中实例方法的参数列表中。

一旦你完成了它,它就会起作用,因为所有方法都是python虚拟的。