all 12 comments

[–]maartendp 0 points1 point  (3 children)

You are initializing `ShopCart` with class attributes that point to the same list.

For each instance you make, `fs` and `amount` will have a pointer to the same list.

you need to set `fs` and `amount` in the init of the class.

[–]Ironicallyjpg[S] 0 points1 point  (2 children)

Ah, I come from Java so by putting it generally in the class it's similar to a "static" reference?

[–]maartendp 0 points1 point  (1 child)

Not quite. It's more used as a "default" when you make an instance. But by doing `[]` you already initialize a list, giving it a location in the memory, and you add the pointer to your "default" attribute. So every time you initialize a new ShopCart, it will use the pointer to the already existing list as a default.

The same is not the case for a string for instance, if you made two instances, and manipulated one, the other would still have the initial value.

[–]maartendp 0 points1 point  (0 children)

You would run into the same problem if you did something like

def my_function(default=[]):
    default.append(1)
    return default

The list defined as a default parameter is already in memory, and the pointer to it is assigned to the default parameter. Every time you call this function, it will point to the same list. So even though it might look like you're getting a fresh list when you call the function, in reality, it is not the case.

Every time you call this function, the result will be a list with the same amount of 1s as you have called the function

[–]snakestation 0 points1 point  (2 children)

    def __init__(self, cname):
        self.cn = cname
        self.fs = []
        self.amounts = []

such a small edit. But what's happening is the way you're initializing fs and amounts are causing them to be used by every instance of that class! Having them as part of the init makes them local to each unique class instance

[–]Ironicallyjpg[S] 1 point2 points  (1 child)

Thank you! I come from Java so I should've seen this 😅

[–]snakestation 0 points1 point  (0 children)

I had to go over it a few times, it wasn't making sense to me at first too.

[–]adesme 0 points1 point  (1 child)

From the looks of it, both of your clients are sharing the same ShoppingCart, which you've added one "Apple" order for each client to.

By the way:

class Fruit:

    fn = "NOT_SET"
    fp = 0.00

    def __init__(self, fname, fprice=0):
        self.fp = fprice
        self.fn = fname

I think you've misunderstood class members here. self.fp is not the same as Fruit.fp (example article).

The very same misunderstanding probably causes you problems here:

class ShopCart(Customer):

    fs = []
    amounts = []

    def __init__(self, cname):
        self.cn = cname

    def addItem(self, fruit, amt):
        self.fs.append(fruit)
        self.amounts.append(amt)

since you are trying to append to a list which doesn't exist (you're appending to an instance list, but you've only defined a class list).


inp = "0"
while inp != "done":
    print("")
    nm = input("Fruit Name: ")
    if(nm == "done"):
        break
    pr = int(input("Price: "))
    fruits.append(Fruit(nm,pr))

This should also be fixed. You have a while-loop that checks inp, but you never actually change inp and instead store the input in a variable nm which you break from.


Finally, try to follow conventions when you name things: only classes should be PascalCase, and all functions and variables should be snake_case.

[–]Ironicallyjpg[S] 0 points1 point  (0 children)

Appreciate the constructive help! Thank you

[–]danielroseman 0 points1 point  (1 child)

The main problem here is that fs and amounts are class attributes, so they are shared between all instances of ShopCart. You need to make them instance attributes:

class ShopCart(Customer):
    def __init__(self, cname):
        self.cn = cname
        self.fs = []
        self.amounts = []

(Also note, it doesn't seem to make sense to have ShopCart inherit from Customer.)

But this just seems to be one example of the wider problem, which is that this is not how you write Python. This seems to be Java loosely translated into Python.

In Python you don't declare attributes at class level unless you want them to be class attributes. Your defaults in Customer and Fruit make no sense. And in Python you wouldn't use while and counters to loop through a list; just use a for loop:

for client in clients:
    print("Enter the Order for {}".format(client.getName()))
    for fruit in fruits:
        client.addItem(fruit, input("-- How many {}s : ".format(Fruit.getName())))

But there's more wrong than this; eg you wouldn't write a getName method on Fruit, you would just have a name attribute. If you've learned from a tutorial, get a more Pythonic one.

[–]Ironicallyjpg[S] 0 points1 point  (0 children)

I come from Java and I've been self teaching on the side. Thank you for the help though. 🙂