Python:如何继承和重写

发布于 2024-09-02 08:29:21 字数 732 浏览 7 评论 0原文

考虑这种情况:

我得到一个 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__ 方法看起来如何?

注意:这篇文章已由原始发布者编辑,以纳入评论中建议的更改,这就是为什么某些建议看起来多余或不正确的原因。

Consider this situation:

I get an object of type A which has the function f:

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

and I get an instance of this class, but I want to override the f function, yet save the rest of the functionality of A. So what I was thinking was something of the sort:

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

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

and the usage would be:

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

What I want is a sort of copy constructor that gets a parent of the current class (A), and returns an instance of this class (B).

How do you do such a thing? How would the __init__ method look?

Note: this post has been edited by the original poster to incorporate changes suggested in the comments, which is why some of the suggestions look redundant or incorrect.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

荭秂 2024-09-09 08:29:21

如何“基于”类 A 之一构造子类 B 的对象完全取决于后者如何保持状态(如果有),以及你如何最好地到达该状态并将其复制过来。在您的示例中,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

状态位于两个实例属性 _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

这是最常见的和正常的方法,子类接受并直接实现其对超类的状态依赖——它非常简单和线性。

您通常会在 A'__init__' 中查找 A 的实例状态方面,因为大多数正常、简单的 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)

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

是否值得使用这四行“魔法”来代替我首先建议的简单作业?大多数情况下,不——简单更好。但是,如果 A 做了任何特殊的事情或者受到外部代码改变其状态的影响,那么这个解决方案可能会更强大和更通用(这就是您通过接受其复杂性而得到的结果)。因此,您必须知道后一种情况是否适用(然后“使用与状态相关的特殊方法的大枪”),或者 A 及其实例是否是“非常正常的普通实例” ,在这种情况下,我强烈建议选择简单和清晰。

How you construct an object of subclass B "based on" one of class A depends exclusively on how the latter keeps state, if any, and how do you best get to that state and copy it over. In your example, instances of A are stateless, therefore there is absolutely no work you need to do in B's '__init__'. In a more typical example, say:

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

the state would be in the two instance attributes _x and _y, so those are what you need to copy over:

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

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

This is the most common and normal approach, where the subclass accepts and directly implements its state-dependence on the superclass -- it's very straightforward and linear.

You normally look for A's instance state aspects in A's '__init__', because most normal, straightforward Python code establishes instance state at initialization (attributes might be added and removed later, or even from code outside of the class's body, but that's not common and generally not advisable).

It is possible to add a little touch of "magic" (introspection-based programming), e.g...:

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)

getstate is a special method that classes may define -- if they do, it's used (e.g. by pickling) to "get the state" of their instances for serialization purpose (otherwise, the instance's __dict__ is deemed to be the instance's "state"). It may return a dict (in which case the .update call updates self's state), but it may also return anything else if the class also defines a __setstate__ that accepts it (so this code tries that route first, before falling back to the update possibility). Note that in this use case either or both of the special methods would be inherited from A -- I wouldn't define / override them in B (unless there are further subtle goals to be achieved that way of course;-).

Is it worth using these four lines of "magic" in lieu of the simple assignments I first suggested? Mostly, no -- simplicity is preferable. But if A does anything special or is subject to external code altering its state, this solution can be more powerful and general (that's what you're buying by accepting its complication). So, you have to know if the latter case applies (and then "go for the big guns" of the special state-related methods), or if A and its instances are "pretty normal vanilla ones", in which case I would strongly recommend choosing simplicity and clarity instead.

一生独一 2024-09-09 08:29:21

试试这个:

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

Try this:

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())

Note, I'm using Python 3, which is the reason for print taking the arguments in parenthesis.

Output:

in f
in h
in B:f
in h
凶凌 2024-09-09 08:29:21

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

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

You need to put the self argument into the argument list for instance methods in python.

Once you've done that, it will just work, because all methods are virtual in python.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文