Python继承结构和参数

发布于 2025-01-31 02:24:44 字数 896 浏览 2 评论 0 原文

我正在尝试设计一种类结构,该类别允许用户定义自己的类,以超载其他类中的预定义方法。在这种情况下,用户将创建C类,以超载D。 d使用d的其他方法。我遇到的问题是如何将“值”从A和B传递到D而忽略它传递给C。我当前写的内容将产生错误,因为C没有“值”作为参数。

我知道我可以将“值”(或 *args)添加到C的init方法和超级呼叫中,但我不想知道其他类需要哪些输入才能将新类添加到A和B中。如果我交换C和DI的顺序不会出现错误,但是我不会使用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

I am trying to design a class structure that allows the user to define their own class that overloads predefined methods in other classes. In this case the user would create the C class to overload the "function" method in D. The user created C class has common logic for other user created classes A and B so they inherit from C to overload "function" but also inherit from D to use D's other methods. The issue I am having is how to pass "value" from A and B to D and ignore passing it to C. What I currently have written will produce an error as C does not have "value" as an argument.

I know that I can add "value" (or *args) to C's init method and the super call but I don't want to have to know what inputs other classes need in order to add new classes to A and B. Also, if I swap the order of C and D I won't get an error but then I don't use C's overloaded "function". Is there an obvious way around this?

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

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

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

发布评论

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

评论(2

忆梦 2025-02-07 02:24:44

本质上,您需要做两件事来使您的 __ INT __ 方法在Python中使用多个继承效果很好:

  1. 始终采用 ** Kwargs 参数,并始终调用 super() -a-super/59833056#59833056“>即使您认为自己是基类。仅仅因为您的超级类是 object 并不意味着您是
  2. 不要通过您的父班的 __ INT __ 明确地参数; 仅通过 ** kwargs < /a>。您的父级不一定是您按照方法解析顺序进行的下一个类别,因此位置参数可能会传递给其他错误的 __ INT __ INT __ 方法。

这称为“合作子分类”。让我们尝试使用您的示例代码:

class D:
    def __init__(self, value, **kwargs):
        self.value = value
        super().__init__(**kwargs)
    
    def function(self):
        return self.value

class C:
    # add **kwargs parameter
    def __init__(self, **kwargs):
        # pass kwargs to super().__init__
        super().__init__(**kwargs)
    
    def function(self):
        return self.value * 2

class B(C, D):
    # don't take parent class's value arg explicitly
    def __init__(self, **kwargs):
        # pass value arg via kwargs
        super().__init__(**kwargs)

class A(C, D):
    # don't take parent class's value arg explicitly
    def __init__(self, **kwargs):
        # pass value arg via kwargs
        super().__init__(**kwargs)

演示:

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

请注意, value 必须传递给 a 构造函数作为关键字参数,而不是作为位置参数。还建议在调用 super.value = value super().__ init __ in __ 之前设置 self.value = value

我还简化了类C(对象): to 类C: super(c,self) 超级()因为它们在Python 3中是等效的。

Essentially, there are two things you need to do to make your __init__ methods play nice with multiple inheritance in Python:

  1. Always take a **kwargs parameter, and always call super().__init__(**kwargs), even if you think you are the base class. Just because your superclass is object doesn't mean you are last (before object) in the method resolution order.
  2. Don't pass your parent class's __init__ arguments explicitly; only pass them via **kwargs. Your parent class isn't necessarily the next one after you in the method resolution order, so positional arguments might be passed to the wrong other __init__ method.

This is called "co-operative subclassing". Let's try with your example code:

class D:
    def __init__(self, value, **kwargs):
        self.value = value
        super().__init__(**kwargs)
    
    def function(self):
        return self.value

class C:
    # add **kwargs parameter
    def __init__(self, **kwargs):
        # pass kwargs to super().__init__
        super().__init__(**kwargs)
    
    def function(self):
        return self.value * 2

class B(C, D):
    # don't take parent class's value arg explicitly
    def __init__(self, **kwargs):
        # pass value arg via kwargs
        super().__init__(**kwargs)

class A(C, D):
    # don't take parent class's value arg explicitly
    def __init__(self, **kwargs):
        # pass value arg via kwargs
        super().__init__(**kwargs)

Demo:

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

Note that value must be passed to the A constructor as a keyword argument, not as a positional argument. It's also recommended to set self.value = value before calling super().__init__.

I've also simplified class C(object): to class C:, and super(C, self) to just super() since these are equivalent in Python 3.

小苏打饼 2025-02-07 02:24:44

因此,我正在尝试理解A和B的点。我猜想也许您想混合超级阶级行为,有时还会有本地行为。因此,假设A只是将行为混合在一起,而B具有一些局部行为和状态。

如果您不需要自己的状态,则可能不需要 __ Init __ 。因此,对于 a c 只会省略 __ INIT __

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': {}}"

我保留了Python2语法,假设您可能仍在使用它,但是正如另一个答案所指出的那样,Python3简化了 super()语法,您确实应该现在使用Python3。

如果交换C和D,则将更改Python方法解决顺序,这确实会更改呼叫A.功能解决的方法。

So I'm trying to understand the point of A AND B. I'm guessing that maybe you want to mix in the superclass behavior and sometimes have local behavior. So suppose A is just mixing together behaviors, and B has some local behavior and state.

If you don't need your own state, you probably don't need an __init__. So for A and C just omit __init__.

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': {}}"

I've kept python2 syntax assuming you might still be using it, but as another answer points out, python3 simplifies super() syntax, and you really should be using python3 now.

If you swap C and D you are changing the python method resolution order, and that will indeed change the method to which a call to A.function resolves.

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