简体   繁体   English

Python多重继承不显示类变量或第二个继承基类的方法

[英]Python multiple inheritance is not showing class variables or method of second inherited base class

Hello awesome community, I was learning the OOPS concepts with python as a part of my curriculum. 您好,社区,我正在学习OOPS概念与python作为我的课程的一部分。 I am having a problem with multiple inheritance in python. 我在python中遇到多重继承问题。 The following is my code: 以下是我的代码:

#!/usr/bin/env python

class Base1(object):
    def __init__(self):
        self.base1var = "this is base1"


class Base2(object):
    def __init__(self):
        self.base2var = "this is base2"

class MainClass(Base1, Base2):
    def __init__(self):
        super(MainClass, self).__init__()


if __name__ == "__main__":
    a = MainClass()
    print a.base1var
    print a.base2var

and when running, I am getting the following error 并且在运行时,我收到以下错误

print a.base2var
AttributeError: 'MainClass' object has no attribute 'base2var'

If I swap the order of classes inherited, the variable name in the error changes accordingly. 如果我交换继承的类的顺序,则错误中的变量名会相应地更改。

Am I using super() wrong when I want to call the constructors of the two inherited classes? 当我想调用两个继承类的构造函数时,我是否使用了super()错误?

How can I correctly inherit from multiple base classes and use the variables and methods in the main class without this error? 如何才能正确地从多个基类继承并使用主类中的变量和方法而不会出现此错误?

Thank you. 谢谢。

You need to add a super call to Base1 so that Base2's __init__ will get called after Base1's. 你需要向Base1添加一个super调用,以便在Base1之后调用Base2的__init__ You can also add a super call to Base2. 您还可以向Base2添加super呼叫。 It's not necessary, but it won't hurt. 这没有必要,但不会受到伤害。

class Base1(object):
    def __init__(self):
        super(Base1, self).__init__()
        self.base1var = "this is base1"

class Base2(object):
    def __init__(self):
        #super(Base2, self).__init__()
        self.base2var = "this is base2"

class MainClass(Base1, Base2):
    def __init__(self):
        super(MainClass, self).__init__()


if __name__ == "__main__":
    a = MainClass()
    print a.base1var
    print a.base2var

output 产量

this is base1
this is base2

BTW, you really should be using Python 3. super is much nicer in modern Python. 顺便说一下,你真的应该使用Python 3.在现代Python中, super更好。 :) :)

If you use super() , you must use it consistently to ensure all classes' methods are called. 如果使用super() ,则必须始终如一地使用它以确保调用所有类的方法。 Your Base1 and Base2 classes should also call super(...).__init__() in their __init__() methods. 你的Base1Base2类也应该在它们的__init__()方法中调用super(...).__init__() This will ensure that all classes in the method resolution order are eventually called. 这将确保最终调用方法解析顺序中的所有类。

This does get a little tricky when not all __init__() methods have an empty argument list. 当并非所有__init__()方法都有一个空参数列表时,这确实有点棘手。 At some point, super() will have you calling object.__init__() , and that never takes any arguments. 在某些时候, super()会让你调用object.__init__() ,并且永远不会接受任何参数。 The trouble is, you might not know which classes this might happen in ahead of time. 麻烦的是,您可能不知道这可能会提前发生在哪个类中。 You can remedy this by creating an object subclass that takes any number of arguments in __init__() , and deriving from that. 您可以通过创建一个object子类来解决这个问题,该子类在__init__()中接受任意数量的参数,并从中派生出来。 That class needn't call object.__init__() because that method doesn't actually do anything (or, if you're paranoid that that might change, you can call object.__init__() without using super() ). 该类不需要调用object.__init__()因为该方法实际上并没有做任何事情(或者,如果你可能会改变偏执,你可以在不使用super()情况下调用object.__init__() super() )。

In general, super() requires extra care in argument handling because you might not know which class will be next in the method resolution order, since users of your code might make new classes using your base classes in combinations you haven't anticipated. 通常, super()在参数处理中需要格外小心,因为您可能不知道方法解析顺序中的下一个类,因为代码的用户可能会使用您未预期的组合使用基类创建新类。 So you'll need to do some work to make sure the method signatures in all your classes are compatible. 因此,您需要做一些工作以确保所有类中的方法签名兼容。

For more information, see Raymond Hettinger's seminal Python's Super() Considered Super . 有关更多信息,请参阅Raymond Hettinger的开创性Python的Super()Considered Super

Basically what is happening is that Python is looking through the parent classes (and their parents, etc. See the link at the end of this paragraph) for some method __init__ . 基本上发生的事情是Python正在查看父类(及其父母等,请参阅本段末尾的链接)以获取某些方法__init__ It reads the classes left to right so it sees Base1 first. 它从左到右读取类,因此它首先看到Base1 Since Base1.__init__ exists, that method is called. 由于Base1.__init__存在,因此调用该方法。 Read a more detailed explanation at this answer . 这个答案中阅读更详细的解释。

I believe the only way to call all of the appropriate methods is to do so manually 我认为调用所有适当方法的唯一方法是手动完成

class MainClass(Base1, Base2):
    def __init__(self):
        Base1.__init__(self)
        Base2.__init__(self)

then 然后

a = MainClass()
print(a.base1var)
print(a.base2var)

prints 版画

this is base1
this is base2

Base1 __init__ overrides Base2 __init__.py so base2var is never created. Base1 __init__会覆盖Base2 __init__.py因此永远不会创建base2var

You should use super , see How does Python's super() work with multiple inheritance? 你应该使用super ,看看Python的super()如何与多重继承一起工作?

It is not mistake to use the super but not for that goal.Explained super I have changed your code 使用超级而不是用于那个目标并不是错误。解释超级我已经改变了你的代码

#!/usr/bin/env python

class Base1(object):
    def __init__(self):
        self.base1var = "this is base1"


class Base2(object):
    def __init__(self):
        self.base2var = "this is base2"

class MainClass(Base2, Base1):
    def __init__(self):
        super(MainClass, self).__init__()


if __name__ == "__main__":
    a = MainClass()
    print (a.base2var)

Than you have 比你有

this is base2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM