Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python类继承设计:假装看起来像鸭子,但不要';庸医_Python_Python 3.x_Class_Multiple Inheritance - Fatal编程技术网

Python类继承设计:假装看起来像鸭子,但不要';庸医

Python类继承设计:假装看起来像鸭子,但不要';庸医,python,python-3.x,class,multiple-inheritance,Python,Python 3.x,Class,Multiple Inheritance,我今天已经搜索了几个小时,但没有得到一个最新的令人满意的明确答案 假设我们有两个特殊的类,它们都有重叠的方法名和特定的单独方法。除去不必要的部分,让我们使用以下类 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

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

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

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'
具体问题:

  • 我们是否必须为此特定实例初始化父级?如果是,应如何使用
    super()
  • 这将真正帮助我摆脱
    isinstance(x,A)
    isinstance(x,B)
    类型的查询。是否有任何最佳实践不鼓励此类使用?注意,在我的例子中,pythonicduck类型对我来说真的不是那么相关。对于不同的计算算法,必然会出现很多分支。因此,我实际上是将类用作数据绑定容器,而不是将它们用作状态记录器。换句话说,它们的实例数据几乎没有变化。但它们的数据在不同的分支中使用,这取决于它们是哪个类。因此,获得合适的对象对我来说至关重要

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

    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'
    

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

    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'
    

    你说“变形成这样”是什么意思?两者都是。是的,您应该使用
    super
    来确保在子类化时调用所有相关方法。或者,如果你不想让它成为一个子类,为什么要子类化?@jornsharpe如果你要求
    a
    B
    拥有的任何方法,从
    C
    ,它的响应将与
    a
    B
    一样。即使我已经覆盖了所有的方法,我仍然需要调用super吗?duck类型表示您不关心对象是否是某个对象的子类,只关心它是否具有相关的属性。目前还不清楚您实际上想要实现什么,但您可能不需要继承。你真的试过这些吗?发生了什么事?@Jornsharpe看一看问题2。你什么意思?这是我简化的一个实际问题。我不知道该注意什么。这就是为什么我问你“变形成这些东西”是什么意思?两者都是。是的,您应该使用
    super
    来确保在子类化时调用所有相关方法。或者,如果你不想让它成为一个子类,为什么要子类化?@jornsharpe如果你要求
    a
    B
    拥有的任何方法,从
    C
    ,它的响应将与
    a
    B
    一样。即使我已经覆盖了所有的方法,我仍然需要调用super吗?duck类型表示您不关心对象是否是某个对象的子类,只关心它是否具有相关的属性。目前还不清楚您实际上想要实现什么,但您可能不需要继承。你真的试过这些吗?发生了什么事?@Jornsharpe看一看问题2。你什么意思?这是我简化的一个实际问题。我不知道该注意什么。这就是为什么我要问重写的原因是
    C
    的行为实际上不像
    A
    B
    ,因此我试图得到一个泛型类,它的行为仍然像A或B,但不会像它们那样。因此,我不会使用
    A
    B
    中的任何一种,但如果需要,它将以
    A
    B
    的格式提供必要的输出。这通常对您的设计不是一个好迹象。您应该后退一步,尝试解决这个问题,这样您的类型才有意义。一般来说,继承应满足“是一种”关系。如果我有一个class
    Car
    ,和一个子类
    Ford(Car)
    ,这是有道理的,因为每一辆Ford也是一辆车。如果您有一个
    Cat
    类,并且您想编写一个
    Dog
    类,那么使用继承是没有意义的,即使这两个类在很大程度上是相似的。(您将创建一个
    Animal
    父类)。这些显然是简单化的例子,但我希望它们能有所帮助。它们实际上满足了你的汽车类比。但是想象一下,我在
    C
    上安装了一台电动发动机。在你的类比中,我有两个类
    汽车
    卡车
    。而
    C
    变成了电动汽车或卡车。他们旧的基于汽油的计算将不再有意义,但我想在任何现有的计算中使用电动汽车或卡车。然而,我必须告诉我的旧代码库,这仍然是一辆汽车,并询问你想从中得到什么。在那里,我将有一个单独的、抽象的
    引擎
    类,可以细分为电动和汽油(以及氢等)引擎。基本上,与这些可变元素交互的部分不应该关心它们正在使用哪个实现。如果您不熟悉它们,您可能想了解Java接口。Python没有直接的类比,但它是设计程序的一种有用方法。那么,回答你的问题,答案是否定的。像这样使用继承不会破坏任何东西,而且(据我所知)Python的任何内部机制都不会受到影响。重写的原因是
    C
    实际上没有影响