OOP Class instance containing a list of class instances

Imagine the following scenario:

We have multiple car owners. (Class “owner”)
We have multiple cars. (Class “car”)

There could be any amount of car owners.
Each car owner may have any amount cars in his possession.
Each car has its own market value in dollars $.

Let’s say we want to count the total market value of all cars in possession of each owner, for example:

John owns the following cars:

  1. Pontiac, value $100
  2. Ford, value $500
  3. Toyota, value $200

John owns a total of 100+500+200 = $ 800

Mike owns the following cars:

  1. Cadillac, value $200
  2. Mercury, value $300
  3. Jaguar, value $400
  4. Pontiac, value $700
  5. Sunbeam, value $500

Mike owns a total of 200+300+400+700+500= $ 2100

Question:
How do we properly structure the classes, and how do we go about counting the total value owned by each owner?

The approach I’ve taken was to define a class “owner”, and a separate independent class “car”.
I then tried to define an empty list inside class “owner” into which I would store the “car” instances.

However,

I’ve hit a wall:
I wanted to create a function inside the “owner” class from which I would iterate through all cars in possession of the owner to telly up the values of each car.
The problem is that I would find no way how I could access the attributes of “car” from inside the “owner” class.

I think this is the wrong approach.

What would be the proper way to deal with this problem?

This makes perfect sense so far, and the roadblock (heh) you are imagining doesn’t really exist.

Attributes of every Python object are accessible from anywhere by default - there is no built-in “protection”. As long as you can write code that gives you the car object itself, you can then just stick on the attribute access. So for example if you have

class Car:
    def __init__(self, price):
        self.price = price

(of course the real thing might have a bunch more stuff in it)

then you don’t have to be writing code inside the class to use the attribute:

my_car = Car(100)
print(my_car.price) # no problem

And similarly you can do the same thing inside another class’ code:

class Owner:
    # other stuff....

    def total_value(self):
        return sum(car.value for car in self.cars)

Of course, if you want to add some kind of protection, or even just a different interface (so that you can say “yes, the Car has a value attribute right now, but you shouldn’t use that, because I might want to change the implementation later”) - you certainly can do that, too.

1 Like

Thanks, this solved my problem!
Danke schoen.

There could be a Market class that provides a method for pricing things. Owners can go over their list of cars asking an instance of Market (e.g. european_market, northamerican_market) to price them.

1 Like

Good idea.
The market class might even contain a set of modifiers, such that you start off with the base value of the car and then you modify its value according to the attributes of the market class, eg market origin (eu, us, etc), current interest rate, seasonality, inflation, etc, to end up with a modified price of the car.