Python:如何继承和重写

Python:如何继承和重写,python,inheritance,overriding,Python,Inheritance,Overriding,考虑这种情况: 我得到一个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):

考虑这种情况:

我得到一个
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

你是怎么做这种事的?
\uuuu init\uuu
方法看起来如何

注意:这篇文章由原始海报编辑,以包含评论中建议的更改,这就是为什么有些建议看起来多余或不正确的原因。

尝试以下方法:

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())
注意,我使用的是Python3,这就是
print
将参数放在括号中的原因

输出:

in f
in h
in B:f
in h

对于python中的实例方法,需要将
self
参数放入参数列表中


一旦你做到了这一点,它就会起作用,因为所有的方法在python中都是虚拟的。

你如何基于“类
A
中的一个”构造子类
B
”的对象完全取决于后者如何保持状态(如果有的话),以及如何最好地达到该状态并复制它。在您的示例中,
A
的实例是无状态的,因此您完全不需要在
B
中执行任何工作。在更典型的示例中,假设:

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
状态将位于两个实例属性
\ux
\uy
,因此您需要复制它们:

class B(A):
     def __init__(self, a):
        self._x = a._x
        self._y = a._y

     def f(self):
         print 'in B->f,', self._x
这是最常见和最正常的方法,其中子类接受并直接实现其对超类的状态依赖——这是非常简单和线性的

通常,您会在
A
中查找
的实例状态方面,因为大多数普通、简单的Python代码都会在初始化时建立实例状态(属性可能会在以后添加和删除,甚至从类体之外的代码中删除,但这并不常见,通常也不可取)

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

是类可以定义的一种特殊方法——如果它们定义了,则使用它(例如,通过酸洗)来“获取其实例的状态”,以便进行序列化(否则,实例的
\uuu dict\uuu
被视为实例的“状态”)。它可能会返回一个dict(在这种情况下,
.update
调用updates
self
的状态),但如果类还定义了一个接受它的
\uuuu setstate\uuuuu
,它也可能会返回任何其他内容(因此该代码首先尝试该路由,然后返回到更新可能性)。请注意,在这个用例中,两种特殊方法中的一种或两种都将继承自
A
——我不会在
B
中定义/覆盖它们(当然,除非有其他微妙的目标需要通过这种方式实现;-)


用这四行“魔法”代替我最初建议的简单作业值得吗?大多数情况下,不,简单更可取。但是,如果
A
做了任何特殊的事情,或者外部代码改变了它的状态,那么这个解决方案可以更强大、更通用(这就是你接受它的复杂性所购买的)。因此,您必须知道后一种情况是否适用(然后是特殊状态相关方法的“大炮”),或者
A
及其实例是否是“非常普通的普通实例”,在这种情况下,我强烈建议您选择简单和清晰。

它与OP的代码有什么不同?他似乎只忘记了
self
。顺便问一下,python中的虚拟方法是什么意思?@Bunny Rabbit:Douglas的意思是
virtual
,就像
C++
一样,其中必须将方法显式定义为
virtual
,以使其可重写。
a
应该表示什么?Guy,您需要先阅读
\uuuuu init\uuuu()
方法。不要把它和继承语法混淆了。这正是我想要的。谢谢+1-我今天读到的最有用的东西是:“取决于……后者如何保持状态,你如何……复制它”
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)