I'm trying to replicate the API of a Java library for a vehicle routing problem and it's highlighted something I don't understand about Python classes.
A vehicle fleet can be broken down into two basic criteria; the first is the types of vehicle you own (instances of VehicleType
to define capacities, running costs etc.) and individual vehicles (Vehicle
with different shift patterns etc.).
In my simplified example, I want to define one VehicleType
and then a single Vehicle
that takes the attributes of the VehicleType
passed to the constructor. Following the answer by Lennart here, using __getattr__
works perfectly in a general case. However, imagine that I have a driver of one van out of 50 that has a special qualification to carry something hazardous, so I want to add an extra capacity property on the Vehicle
instance. I tried the following:
class VehicleType(object):
def __init__(self, fixed_cost=0, cost_per_distance=0, cost_per_time=0):
self.capacities = {}
self.fixed_cost = fixed_cost
self.cost_per_distance = cost_per_distance
self.cost_per_time = cost_per_time
def add_capacity_dimension(self, dimension_id, dimension_size):
""" Define a package type and how many of them this vehicle type can carry """
self.capacities[dimension_id] = dimension_size
class Vehicle(object):
def __init__(self, vehicle_type=None, identifier=None):
self._vehicle_type = vehicle_type
self.identifier = identifier
def add_capacity_dimension(self, dimension_id, dimension_size):
self.capacities[dimension_id] = dimension_size
def __getattr__(self, name):
return getattr(self._vehicle_type, name)
if __name__ == '__main__':
van_type = VehicleType()
van_type.add_capacity_dimension("general items", 34)
special_van = Vehicle(vehicle_type=van_type)
special_van.add_capacity_dimension("hazardous chemicals", 50)
print("Capacities of special van: {}".format(special_van.capacities))
print("Capacity of van_type: {}".format(van_type.capacities)) # Why?
I don't understand why my approach has also affected the capacities
of the van_type
. Vehicle
does not directly inherit from VehicleType
and I have defined add_capacity_dimension
within the Vehicle
class. This also contradicts my understanding of the docs about __getattr__
:
Called when an attribute lookup has not found the attribute in the usual places (i.e. it is not an instance attribute nor is it found in the class tree for self). name is the attribute name.
Can someone please explain why the instance van_type
is also affected here?