Python继承结构和参数

Python继承结构和参数,python,multiple-inheritance,Python,Multiple Inheritance,我试图设计一个类结构,允许用户定义自己的类,重载其他类中预定义的方法。在这种情况下,用户将创建C类以重载D中的“function”方法。用户创建的C类对于其他用户创建的类A和B具有公共逻辑,因此它们从C继承以重载“function”,但也从D继承以使用D的其他方法。我遇到的问题是如何将“值”从A和B传递到D,而忽略将其传递到C。我当前编写的内容将产生一个错误,因为C没有“值”作为参数 我知道我可以向C的init方法和super调用添加“value”(或*args),但我不想知道其他类需要什么输入

我试图设计一个类结构,允许用户定义自己的类,重载其他类中预定义的方法。在这种情况下,用户将创建C类以重载D中的“function”方法。用户创建的C类对于其他用户创建的类A和B具有公共逻辑,因此它们从C继承以重载“function”,但也从D继承以使用D的其他方法。我遇到的问题是如何将“值”从A和B传递到D,而忽略将其传递到C。我当前编写的内容将产生一个错误,因为C没有“值”作为参数

我知道我可以向C的init方法和super调用添加“value”(或*args),但我不想知道其他类需要什么输入才能向A和B添加新类。此外,如果我交换C和D的顺序,我不会得到错误,但我不会使用C的重载“函数”。有没有一个明显的解决办法

class D(SomethingElse):
    def __init__(self, value, **kwargs):
        super(D, self).__init__(**kwargs)

        self.value = value

    def function(self):
        return self.value

    def other_method(self):
        pass

class C(object):
    def __init__(self):
        super(C, self).__init__()

    def function(self):
        return self.value*2

class B(C, D):
    def __init__(self, value, **kwargs):
        super(B, self).__init__(value, **kwargs)

class A(C, D):
    def __init__(self, value, **kwargs):
        super(A, self).__init__(value, **kwargs)



a = A(3)
print(a.function())
>>> 6

基本上,要使您的
\uuuu init\uuu
方法在Python中的多重继承中发挥良好作用,需要做两件事:

  • 始终使用
    **kwargs
    参数,并始终调用
    super()。仅仅因为你的超类是
    对象
    ,并不意味着你是最后一个(在
    对象
    之前)
  • 不要显式地传递父类的
    \uuu init\uu
    参数。在方法解析顺序中,父类不一定在您之后,因此位置参数可能会传递给错误的其他
    \uuuuu init\uuuu
    方法
  • 这被称为“合作子类化”。让我们试试您的示例代码:

    D类:
    定义初始值(自身、值、**kwargs):
    自我价值=价值
    超级()
    def功能(自我):
    回归自我价值
    C类:
    #添加**kwargs参数
    定义初始(自我,**kwargs):
    #将kwargs传递给super()__
    超级()
    def功能(自我):
    返回self.value*2
    B类(C、D):
    #不要显式获取父类的值arg
    定义初始(自我,**kwargs):
    #通过kwargs传递值arg
    超级()
    A类(C、D类):
    #不要显式获取父类的值arg
    定义初始(自我,**kwargs):
    #通过kwargs传递值arg
    超级()
    
    演示:

    >a=a(值=3)
    >>>a.价值
    3.
    >>>a.功能()
    6.
    
    请注意,
    value
    必须作为关键字参数而不是位置参数传递给
    A
    构造函数。还建议在调用
    super()之前设置
    self.value=value
    。\uuuu init\uuuu

    class SomethingElse(object):
        def __init__(self, *args, **kwargs):
            self.args = args
            self.kwargs = kwargs
    
    class D(SomethingElse):
        def __init__(self, value, *args,  **kwargs):
            super(D, self).__init__(*args, **kwargs)
    
            self.value = value
    
        def function(self):
            return self.value
    
        def other_method(self):
            return self.__dict__
    
    class C(object):
        #def __init__(self):
        #    super(C, self).__init__()
    
        def function(self):
            return self.value*2
    
    class B(C, D):
        def __init__(self, value, bstate, *args, **kwargs):
            super(B, self).__init__(value, *args, **kwargs)
            self.bstate = bstate
    
        def __repr__(self):
            return (self.__class__.__name__ + ' ' +
                    self.bstate + ' ' + str(self.other_method()))
    
    class A(C, D):
        pass
    
    
    a = A(3)
    b = B(21, 'extra')
    
    a.function()
    6
    
    b.function()
    42
    repr(a)
    '<xx.A object at 0x107cf5e10>'
    repr(b)
    "B extra {'args': (), 'bstate': 'extra', 'value': 21, 'kwargs': {}}"
    

    我还将
    类C(对象):
    简化为
    类C:
    super(C,self)
    简化为
    super()
    ,因为它们在Python3中是等效的。

    本质上,有两件事需要做,才能使
    \u init\u
    方法在Python中更好地处理多重继承:

  • 始终使用
    **kwargs
    参数,并始终调用
    super()。仅仅因为你的超类是
    对象
    ,并不意味着你是最后一个(在
    对象
    之前)
  • 不要显式地传递父类的
    \uuu init\uu
    参数。在方法解析顺序中,父类不一定在您之后,因此位置参数可能会传递给错误的其他
    \uuuuu init\uuuu
    方法
  • 这被称为“合作子类化”。让我们试试您的示例代码:

    D类:
    定义初始值(自身、值、**kwargs):
    自我价值=价值
    超级()
    def功能(自我):
    回归自我价值
    C类:
    #添加**kwargs参数
    定义初始(自我,**kwargs):
    #将kwargs传递给super()__
    超级()
    def功能(自我):
    返回self.value*2
    B类(C、D):
    #不要显式获取父类的值arg
    定义初始(自我,**kwargs):
    #通过kwargs传递值arg
    超级()
    A类(C、D类):
    #不要显式获取父类的值arg
    定义初始(自我,**kwargs):
    #通过kwargs传递值arg
    超级()
    
    演示:

    >a=a(值=3)
    >>>a.价值
    3.
    >>>a.功能()
    6.
    
    请注意,
    value
    必须作为关键字参数而不是位置参数传递给
    A
    构造函数。还建议在调用
    super()之前设置
    self.value=value
    。\uuuu init\uuuu

    class SomethingElse(object):
        def __init__(self, *args, **kwargs):
            self.args = args
            self.kwargs = kwargs
    
    class D(SomethingElse):
        def __init__(self, value, *args,  **kwargs):
            super(D, self).__init__(*args, **kwargs)
    
            self.value = value
    
        def function(self):
            return self.value
    
        def other_method(self):
            return self.__dict__
    
    class C(object):
        #def __init__(self):
        #    super(C, self).__init__()
    
        def function(self):
            return self.value*2
    
    class B(C, D):
        def __init__(self, value, bstate, *args, **kwargs):
            super(B, self).__init__(value, *args, **kwargs)
            self.bstate = bstate
    
        def __repr__(self):
            return (self.__class__.__name__ + ' ' +
                    self.bstate + ' ' + str(self.other_method()))
    
    class A(C, D):
        pass
    
    
    a = A(3)
    b = B(21, 'extra')
    
    a.function()
    6
    
    b.function()
    42
    repr(a)
    '<xx.A object at 0x107cf5e10>'
    repr(b)
    "B extra {'args': (), 'bstate': 'extra', 'value': 21, 'kwargs': {}}"
    

    我还将
    类C(对象):
    简化为
    类C:
    super(C,self)
    简化为
    super()
    ,因为它们在Python3中是等效的。

    所以我试图理解A和B的要点。我猜可能你想要混合在超类行为中,有时会有局部行为。假设A只是混合了一些行为,B有一些局部行为和状态

    如果您不需要自己的状态,则可能不需要
    \uuuu init\uuuu
    。因此,对于
    A
    C
    只需省略
    \uuuu init\uuuu

    class SomethingElse(object):
        def __init__(self, *args, **kwargs):
            self.args = args
            self.kwargs = kwargs
    
    class D(SomethingElse):
        def __init__(self, value, *args,  **kwargs):
            super(D, self).__init__(*args, **kwargs)
    
            self.value = value
    
        def function(self):
            return self.value
    
        def other_method(self):
            return self.__dict__
    
    class C(object):
        #def __init__(self):
        #    super(C, self).__init__()
    
        def function(self):
            return self.value*2
    
    class B(C, D):
        def __init__(self, value, bstate, *args, **kwargs):
            super(B, self).__init__(value, *args, **kwargs)
            self.bstate = bstate
    
        def __repr__(self):
            return (self.__class__.__name__ + ' ' +
                    self.bstate + ' ' + str(self.other_method()))
    
    class A(C, D):
        pass
    
    
    a = A(3)
    b = B(21, 'extra')
    
    a.function()
    6
    
    b.function()
    42
    repr(a)
    '<xx.A object at 0x107cf5e10>'
    repr(b)
    "B extra {'args': (), 'bstate': 'extra', 'value': 21, 'kwargs': {}}"
    
    class SomethingElse(对象):
    定义初始化(self,*args,**kwargs):
    self.args=args
    self.kwargs=kwargs
    D类(某些方面):
    定义初始化(self,value,*args,**kwargs):
    super(D,self)。\uuuuu初始值(*args,**kwargs)
    自我价值=价值
    def功能(自我):
    回归自我价值
    def其他_方法(自身):
    返回自我__
    C类(对象):
    #定义初始化(自):
    #super(C,self)。\uuuuu init\uuuuuuu()
    def功能(自我):
    返回自我值*2
    B类(C、D):
    定义初始值(self、value、bstate、*args、**kwargs):
    super(B,self)。\uuuuu初始值(值,*args,**kwargs)
    self.bstate=bstate
    定义报告(自我):
    返回(self)_