-1
 class Car(object):
    condition = "new"

    def __init__(self):
        self.model =raw_input()
        self.color = raw_input()
        self.mpg   = raw_input()

class Jeep(object):
    condition = "new"

    def __init__(self):
        self.model =raw_input()
        self.color = raw_input()
        self.mpg   = raw_input()


class ElectricCar(Car, Jeep):
    def __init__(self, battery_type):
        self.battery_type=battery_type
        super(ElectricCar, self).__init__()

    def printer(self):
        print self.model
car = ElectricCar('battery')
car.printer()
print car.__dict__

Only 3 times I am getting to enter my entries instead of 6 plus I am confused how to avoid ambiguity as model is in car as well as jeep. How do I tackle them?

Anil_M
  • 10,893
  • 6
  • 47
  • 74
  • 3
    Look at this question for an explanation on multiple inheritance: http://stackoverflow.com/questions/3277367/how-does-pythons-super-work-with-multiple-inheritance. To quote the top answer: "But, briefly: […] For such simple situations, Python will look for the attribute (in this case, __init__) on the class's parents, left to right." – Daniel Diekmeier Apr 12 '16 at 10:56

1 Answers1

0

There are two problems here:

  • Python objects have one dict for storing attributes, there can be no attribute hiding like in other programming languages
  • You are incorrectly using multiple inheritance and super.

Python will not work how you want it to work. Each instance in Python has one shared dict which all classes share for attribute access. This means you cannot hide an attribute, only overwrite it. To do what you want you must a unique name for model in Car and a unique name in Jeep. eg. car_model and jeep_model. A quick test that shows this:

class Parent(object):
    def __init__(self):
        super(Parent, self).__init__()
        self.value = "parent"
    def parent_value(self):
        return self.value

class Child(Parent):
    def __init__(self):
        super(Child, self).__init__()
        self.value = "child"
    def child_value(self):
        return self.value

p = Parent()
assert p.parent_value() == "parent"
c = Child()
assert c.child_value() == "child"
assert c.parent_value() == "child"

You could use "private" variables. These aren't really private, python just does something called name mangling to make them harder to accidentally overwrite.

class Parent(object):
    def __init__(self):
        super(Parent, self).__init__()
        self.__value = "parent"
    def parent_value(self):
        return self.__value

class Child(Parent):
    def __init__(self):
        super(Child, self).__init__()
        self.__value = "child"
    def child_value(self):
        return self.__value

p = Parent()
assert p.parent_value() == "parent"
c = Child()
assert c.child_value() == "child"
assert c.parent_value() == "parent"
print(vars(c)) 
# prints {'_Child__value': 'child', '_Parent__value': 'parent'}
c._Parent__value = "new value"
assert c.parent_value() == "new value"

Finally, your __init__ methods in your base classes do not make a call to super. In non-multiple inheritance this is not necessary for the base class. However, in your case (which uses multiple inheritance) the set of __init__ methods will get to Car.__init__ and then stop without calling Jeep.__init__.

class Car(object):
    def __init__(self):
        print("init car")
        super(Car, self).__init__()
        print("assigning car")
        self.car = "car"

class Jeep(object):
    def __init__(self):
        print("init jeep")
        super(Jeep, self).__init__()
        print("assigning jeep")
        self.jeep = "jeep"

class ElectricCar(Car, Jeep):
    def __init__(self):
        print("init electric car")
        super(ElectricCar, self).__init__()
        print("assigning electric")
        self.electric = "electric"

car = ElectricCar()
# prints the following:
# init electric car
# init car
# init jeep
# assigning jeep
# assigning car
# assigning electric
Dunes
  • 37,291
  • 7
  • 81
  • 97