【问题标题】:Python class inheritance design: Pretend to look like a duck but don't quackPython类继承设计:假装鸭子不嘎嘎
【发布时间】:2018-11-06 09:23:13
【问题描述】:

我今天已经搜索了几个小时,但没有得到最近且令人满意的明确答案。

假设我们有两个特定的类,它们具有重叠的方法名称和特定的单独方法。摆脱不必要的部分让我们使用以下类。

class A():
    def __init__(self, a_arg1, a_arg2):
        self.a_arg1 = a_arg1
        self.a_arg2 = a_arg2

    @property
    def gimme_1(self):
        return self.a_arg1

    @property
    def gimme_2(self):
        return self.a_arg2

    @property
    def prop(self):
        return 'A'

还有

class B():
    def __init__(self, b_arg1, b_arg2, b_arg3):
        self.b_arg1 = b_arg1
        self.b_arg2 = b_arg2
        self.b_arg3 = b_arg3

    @property
    def give_1(self):
        return self.b_arg1

    @property
    def give_2(self):
        return self.b_arg2

    @property
    def give_3(self):
        return self.b_arg3

    @property
    def prop(self):
        return 'B'

我的目标是制作第三个类,它可以演变成其中之一,即,它将具有这两个类所具有的所有方法,并且无论请求哪一个,它都好像它是其中之一。这就是问题标题的动机。

class C(A, B):
    def __init__(self, some_list):
        self.some_list = some_list

    @property
    def gimme_1(self):
        return self.some_list[0]

    @property
    def gimme_2(self):
        return self.some_list[1]

    @property
    def give_1(self):
        return self.some_list[0] ** 2

    @property
    def give_2(self):
        return self.some_list[1] ** 2

    @property
    def give_3(self):
        return self.some_list[2]

    @property
    def prop(self):
        return 'C'

具体问题:

  1. 我们是否必须为此特定实例初始化父级?如果是,应该如何使用super()
  2. 这真的可以帮助我摆脱isinstance(x, A)isinstance(x, B) 类型的查询。是否有任何最佳实践不鼓励这种用法?请注意,在我的情况下,Pythonic 鸭子类型对我来说真的不那么相关。对于不同的计算算法,必然会发生很多分支。因此,我实际上将类用作数据捆绑容器,但没有将它们用作状态记录器。换句话说,他们的实例数据几乎没有变化。但是他们的数据根据​​他们所在的类别在不同的分支中使用。因此,获得合适的对象对我来说至关重要。

【问题讨论】:

  • 你是什么意思“变成其中之一”?它这两者。是的,您应该使用super 来确保在子类化时调用所有相关方法。或者,如果您实际上不希望它成为子类,为什么要进行子类化?
  • @jonrsharpe 如果您询问AB 具有的任何方法,来自C,它会按照AB 的方式进行响应。即使我已经覆盖了所有方法,我还需要调用 super 吗?
  • 鸭子类型意味着你不关心对象是否是/子类,只是它具有相关属性。目前尚不清楚您实际上想要实现什么,但您可能不需要继承。你真的尝试过这些吗?发生了什么?
  • @jonrsharpe 看看问题 2。你是什么意思?这是我简化的一个实际问题。我不知道要注意什么。这就是我问的原因

标签: python python-3.x class multiple-inheritance


【解决方案1】:

与其重写方法,为什么不利用继承的好处呢?让父 __init__s 负责设置实例值,并让它们提供方法实现。

class C(A, B):
    def __init__(self, arg1, arg2, arg3):
        A.__init__(self, arg1, arg2)
        B.__init__(self, arg1**2, arg2**2, arg3)

    @property
    def prop(self):
        return 'C'

【讨论】:

  • 重写的原因是C 的行为并不像AB 因此我试图获得一个仍然像A 或B 一样的泛型类,但是不会像他们那样行事。所以我不会使用AB 中的任何一个,但如果需要,它将以AB 的格式提供必要的输出。
  • 这对您的设计来说通常不是一个好兆头。您应该退后一步并尝试解决此问题,以便您的类型有意义。通常,继承应该满足“是”关系。如果我有一个类Car 和一个子类Ford(Car),这是有道理的,因为每辆福特汽车也是一辆汽车。如果你有一个Cat 类,并且你想编写一个Dog 类,那么使用继承是没有意义的,即使两者在很大程度上相似。 (您将改为创建一个 Animal 父类)。这些显然是简单的例子,但我希望它们有所帮助。
  • 它们实际上满足了您的汽车类比。但是想象一下,我已经为C 安装了一个电动引擎。在你的类比中,我有两个类CarTruckC 变成电动汽车或卡车。他们基于汽油的旧计算不再有意义,但我想在任何现有计算中使用电动汽车或卡车。但是,我必须告诉我的旧代码库,这仍然是一辆车,并询问你想要的任何一个。
  • 我将有一个单独的抽象Engine 类,它可以细分为电动和汽油(以及氢等)发动机。基本上,与这些可变元素交互的部分不应该关心他们使用的是哪个实现。如果您不熟悉它们,您可能想了解 Java 接口。 Python 没有直接的类似物,但它是设计程序的有用方法。
  • 那么回答你的问题,答案是否定的。像这样使用继承不会破坏任何东西,而且(据我所知)Python 的任何内部机制都不会受到影响。
猜你喜欢
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-03
  • 1970-01-01
  • 1970-01-01
  • 2014-03-17
相关资源
最近更新 更多