Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python 2.7 multiple inheritance

Why this simple code doesn't work for Python 2.7 ? Please, help. Most likely I misuse super method in 'New Style' for classes.

class Mechanism(object):
    def __init__(self):
        print('Init Mechanism')
        self.__mechanism = 'this is mechanism'

    def get_mechanism(self):
        return self.__mechanism

class Vehicle(object):
    def __init__(self):
        print('Init Vehicle')
        self.__vehicle = 'this is vehicle'

    def get_vehicle(self):
        return self.__vehicle

class Car(Mechanism, Vehicle):
    def __init__(self):
        super(Car, self).__init__()

c = Car()
print(c.get_mechanism())
print(c.get_vehicle())

The error:

Init Vehicle
Traceback (most recent call last):
  File "check_inheritance.py", line 22, in <module>
    print(c.get_mechanism())
  File "check_inheritance.py", line 7, in get_mechanism
    return self.__mechanism
AttributeError: 'Car' object has no attribute '_Mechanism__mechanism'

EDIT

  1. Fixed def __init(self): in Mechanism class onto def __init__(self):
  2. The correct answer is to use super method in all classes. Not only in Car class. See the answer of Martijn Pieters
  3. Try to avoid double underscore __ for private variables. It is not a Python way (style of code). See the discussion for more info here.
like image 597
FooBar167 Avatar asked Oct 31 '25 20:10

FooBar167


1 Answers

You have 2 issues:

  • You misnamed the __init__ method of Mechanism; you are missing two underscores.

  • Your __init__ methods do not cooperate correctly in a multiple inheritance situation. Make sure you always call super(...).__init__(), in all your __init__ methods.

The following code works:

class Mechanism(object):
    def __init__(self):
        super(Mechanism, self).__init__()
        print('Init Mechanism')
        self.__mechanism = 'this is mechanism'

    def get_mechanism(self):
        return self.__mechanism

class Vehicle(object):
    def __init__(self):
        super(Vehicle, self).__init__()
        print('Init Vehicle')
        self.__vehicle = 'this is vehicle'

    def get_vehicle(self):
        return self.__vehicle

class Car(Mechanism, Vehicle):
    def __init__(self):
        super(Car, self).__init__()

Demo:

>>> c = Car()
Init Vehicle
Init Mechanism
>>> print(c.get_mechanism())
this is mechanism
>>> print(c.get_vehicle())
this is vehicle

You should probably also not use double-underscore names. See Inheritance of private and protected methods in Python for the details, but the short reason is that you do not have a use case here for class-private names, as you are not building a framework meant to be extended by third parties; that's the only real usecase for such names.

Stick to single-underscore names instead, so _mechanism and _vehicle.

like image 171
Martijn Pieters Avatar answered Nov 03 '25 09:11

Martijn Pieters



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!