Python:如何继承和覆盖

Guy*_*Guy 15 python inheritance overriding

考虑这种情况:

我得到一个A具有该功能的类型的对象f.即:

class A:
   def f(self):
      print 'in f'
   def h(self):
      print 'in h'
Run Code Online (Sandbox Code Playgroud)

我得到了这个类的一个实例,但我想覆盖该f函数但保存其余的功能A.所以我在想的是某种东西:

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

     def f(self):
         print 'in B->f'
Run Code Online (Sandbox Code Playgroud)

用法是:

def main(a):
   b = B(a)
   b.f()   #prints "in B->f"
   b.h()   #print "in h"
Run Code Online (Sandbox Code Playgroud)

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

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

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

Ale*_*lli 11

如何构造子类的对象B"基于"类之一A取决于后者如何保持状态(如果有的话),以及如何最好地到达该状态并将其复制.在你的榜样,实例A是无状态的,因此绝对不会有你需要做的工作B'__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
Run Code Online (Sandbox Code Playgroud)

国家将在这两个实例属性_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
Run Code Online (Sandbox Code Playgroud)

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

通常你找A的在实例状态方面AS' '__init__',因为最正常的,简单的Python代码在初始化建立实例状态(属性可能被添加和稍后移除,或者甚至从码外的类的身体的,但是这并不常见,一般不可取).

可以添加的"神奇"(基于内省编程)有点淡淡的,如..:

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)
Run Code Online (Sandbox Code Playgroud)

getstate是一个特殊的方法,类可以定义 - 如果它们这样做,它被用于(例如通过pickle)"获取其实例的状态"以用于序列化目的(否则,实例__dict__被认为是实例的"状态").它可能返回一个dict(在这种情况下,.update调用更新self的状态),但是如果类也定义了__setstate__接受它的话,它也可能返回任何其他内容(因此这段代码首先尝试该路由,然后再回到更新可能性) .请注意,在这个用例中,将继承其中一个或两个特殊方法A- 我不会定义/覆盖它们B(除非当然还有其他微妙的目标要实现;-).

是否值得使用这四行"魔法"来代替我最初建议的简单任务?大多数情况下,不简单是优选的.但是,如果A做任何特殊的事情或受外部代码改变其状态的影响,这个解决方案可以更强大和更通用(这就是你通过接受其复杂性而购买的东西).所以,你必须知道后一种情况是否适用(然后是"寻找特殊状态相关方法的大枪"),或者如果A它的实例是"非常正常的香草",在这种情况下我会强烈推荐选择简洁和清晰度.


ang*_*son 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())
Run Code Online (Sandbox Code Playgroud)

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

输出:

in f
in h
in B:f
in h
Run Code Online (Sandbox Code Playgroud)