处理派生类实例的惯用法?

时间:2017-04-25 21:22:37

标签: python inheritance interface

虽然我每次遇到像这样的问题时都有使用Python的编程经验,但我使用内置的isinstance函数。但是,我不确定这是否是在python中做这些事情的理想方式。

所以,我有一个基类,我的大部分实例都是。

class Base():
  def a(self):
    return 1

我的课程略有不同,如下所示:

class Extended(Base):
  def b(self):
    return 2

现在,有一个第三个类可能具有附加功能,具体取决于接收到的参数,该参数将是之前类之一的实例。

class User():
  def __init__(self, arg):
    ... # do some common work
    if isinstance(arg, Extended):
      ...
      # define more functionality which will call method 'b'
      # at some point during runtime (as event handler or smth)

这真的是在这个简单的例子中使用Python的方法,或者我应该考虑将Base的界面更改为:

class Base2():
  supports_more_func = False

  def a(self):
    return 1

  def b(self):
    pass

class Extended2(Base2):
  supports_more_func = True

  def b(self):
    return 2

class User():
  def __init__(self, arg):
    ... # do some common work
    if arg.supports_more_func:
      ...
      # define more functionality which will call method 'b'
      # at some point during runtime (as event handler or smth)

根据你的家伙,哪一个更好的方法,为什么?

1 个答案:

答案 0 :(得分:0)

一般来说,在进行面向对象编程时,使用isinstance很少是可行的方法,尤其是当您负责设计所使用的类时,因为这会破坏S.O.L.I.D. principles

相反,你应该简单地设计你的类,以便有一个共同定义良好的界面,并使用它。因此,对类型或成员的测试很少是可行的方法。

我的方式是:

class Base2():
  def a(self):
    return 1

  def b(self):
    pass

class Extended2(Base2):
  def b(self):
    # all that extra functionality that was in User.__init__()
    return 2

class User():
  def __init__(self, arg):
    ... # do some common work
    arg.b()

现在我猜这个部分有:

  # define more functionality which will call method 'b'
  # at some point during runtime (as event handler or smth)

有一些数据和处理与User紧密耦合,而不与Extended2紧密耦合,但我很确定有一种优雅的方法可以将这些数据作为参数提供给arg.b()

基本上,我会说99%的时间你需要使用isinstance()做某事,这意味着你有一个设计问题,并且有一个更好的方法来做同样的事情。

以下是关于该主题的一些网络文章: