Hey it's Serge
Hey it's Serge

Reputation: 5

Python combine two classes

I need implement method (i think it's method add) responsible for adding a Сar with an AirPlane. i need to get Class AirCar whose length and weight will be equal to the average between the attributes of the Car and the AirPlane. so my code below

class Car:
        average_speed = 60
        average_length = 5
        cars = []
    
        def __init__(self, model, speed=average_speed, length=average_length):
            self.model = model
            self.speed = speed
            self.length = length
    
    
    class AirPlane(Car):
        average_speed = 300
        average_length = 10
        AirPlane = []
    
        def magic(self):
            super(Car, self).__init__()
    
    
    class AirCar(Car, AirPlane):
        def __add__(self, other):
            if self.cars:
                self.average_speed = sum([car.speed for car in self.cars]) / len(self.cars)
                self.average_length = sum([AirPlane.length for AirPlane in self.AirPlane]) / len(self.AirPlane)
                self.Aircar.append(self)
    
Tesla = Car("Tesla", speed=300, length=4)
Boing = AirPlane('Boing', speed=600, length=20)

Output TypeError: Cannot create a consistent method resolution order (MRO) for bases Car, AirPlane

Upvotes: 0

Views: 1337

Answers (1)

Iguananaut
Iguananaut

Reputation: 23306

I think this might be along the lines of what you're trying to do but I'm not sure:

>>> class Vehicle:
...     average_speed = None
...     average_length = None
...     def __init__(self, model, speed=None, length=None):
...         self.model = model
...         self.speed = speed if speed is not None else self.average_speed
...         self.length = length if length is not None else self.average_length
... 
... 
>>> class Car(Vehicle):
...     average_speed = 60
...     average_length = 5
...     def __add__(self, other):
...         if isinstance(other, Plane):
...             return CarPlane(self.model + other.model,
...                             speed=(self.speed + other.speed) / 2,
...                             length=(self.length + other.length) / 2)
...         return NotImplemented
...
...     __radd__ = __add__
... 
>>> class Plane(Vehicle):
...     average_speed = 300
...     average_length = 10
... 
>>> class CarPlane(Car, Plane):
...     average_speed = (Car.average_speed + Plane.average_speed) / 2
...     average_length = (Car.average_length + Plane.average_length) / 2
>>> car = Car('Tesla')
>>> plane = Plane('Boeing')
>>> carplane = car + plane
>>> carplane
<__main__.CarPlane object at 0x7f5744c8a850>
>>> carplane.model, carplane.speed, carplane.length
('TeslaBoeing', 180.0, 7.5)

Update: If you want to combine any kind of vehicle with any other kind of vehicle you could go further and generate the combined classes on the fly:

>>> class Vehicle:
...     average_speed = None
...     average_length = None
...     _compound_vehicle_classes = {}
... 
...     def __init__(self, model, speed=None, length=None):
...         self.model = model
...         self.speed = speed if speed is not None else self.average_speed
...         self.length = length if length is not None else self.average_length
...
...     def __repr__(self):
...         return f'{self.__class__.__name__}(model={self.model!r}, speed={self.speed}, length={self.length})'
... 
...     def __add__(self, other):
...         if not isinstance(other, Vehicle):
...             return NotImplemented
...         cls_a = self.__class__
...         cls_b = other.__class__
...         if (cls_a is cls_b):
...             cls = cls_a
...         elif False:
...             # exercise to reader: what if cls_a or cls_b is already
...             # a compound vehicle class?  You could still resolve this
...             # by checking the __mro__ of each class, for example; you
...             # could also use this to combine a third or even fourth
...             # type of vehicle into some kind of Voltron ^_~
...             pass
...         else:
...             key = (cls_a, cls_b)
...             if key in self._compound_vehicle_classes:
...                 cls = self._compound_vehicle_classes[key]
...             else:
...                 cls = type(cls_a.__name__ + cls_b.__name__,
...                            (cls_a, cls_b),
...                            {'average_length': (cls_a.average_length + cls_b.average_length) / 2,
...                             'average_speed': (cls_a.average_speed + cls_b.average_speed) / 2})
...                 self._compound_vehicle_classes[key] = cls
...         return cls(self.model + other.model, speed=(self.speed + other.speed) / 2,
...                    length=(self.length + other.length) / 2)
... 
>>> class Car(Vehicle):
...     average_speed = 60
...     average_length = 5
... 
>>> class Plane(Vehicle):
...     average_speed = 300
...     average_length = 10
... 
>>> 
>>> class Boat(Vehicle):
...     average_speed = 20
...     average_length = 100
... 
>>> car = Car('Tesla')
>>> plane = Plane('Boeing')
>>> boat = Boat('Evergreen')
>>> carplane = car + plane
>>> carplane
CarPlane(model='TeslaBoeing', speed=180.0, length=7.5)
>>> planecar = plane + car
>>> planecar
PlaneCar(model='BoeingTesla', speed=180.0, length=7.5)
>>> car + boat
CarBoat(model='TeslaEvergreen', speed=40.0, length=52.5)

Upvotes: 1

Related Questions