Python OOP shopping cart I completed the following task:


  You need to create the foundations of an e-commerce engine for a B2C (business-to-consumer) retailer. You need to have a class for a customer
  called User, a class for items in inventory called Item, and a shopping cart class calledCart. Items go in Carts, and Users can have multiple Carts. Also, multiple items can go into Carts, including more than one of any single item.


I am a new Pythoner, and don't have good knowledge of OOP. I feel the code is not good. I welcome recommendations to improve the code.Here's my code:

class Item(object):
    def __init__(self,itemname,itemprice):
        self.__itemname = itemname
        self.__itemprice = itemprice

    def GetItemName(self):
        return self.__itemname

    def GetItemPrice(self):
        return self.__itemprice

    def ChangeItemPrice(self,newprcie):
        self.__itemprice = newprcie

class Cart(dict):      #cart dict format:  {itemname:[price,number]}
    def ShowCart(self):
        return self   

class User(object):
    def __init__(self, name):    
        self.name = name
        self.__cartlist = {}
        self.__cartlist[0] = Cart()

    def AddCart(self):
        self.__cartlist[len(self.__cartlist)] = Cart()

    def GetCart(self, cartindex = 0):
        return self.__cartlist[cartindex]

    def BuyItem(self, item, itemnum, cartindex = 0):
        try:
            self.__cartlist[cartindex][item.GetItemName()][1] += itemnum
        except:
            self.__cartlist[cartindex].update({item.GetItemName():[item.GetItemPrice(),itemnum]})

    def BuyCancle(self, itemname, itemnum, cartindex = 0):
        pass


if __name__ == '__main__': 

    item1 = Item('apple', 7.8)
    item2 = Item('pear', 5)   

    user1 = User('John')

    user1.BuyItem(item1, 5)
    print("user1 cart0 have: %s" % user1.GetCart(0).ShowCart())

    user1.BuyItem(item2, 6)
    print("user1 cart0 have: %s" % user1.GetCart(0).ShowCart())


    user1.AddCart()
    user1.BuyItem(item1, 5, 1)
    print("user1 cart1 have: %s" % user1.GetCart(1).ShowCart())
I have some notes on how you structured this, note that some are a bit Python specific.

Your attribute names should not have the class name in them. It's redundant because you'll always be accessing them from something else, ie. Item.name is simpler than Item.itemname. Also you shouldn't use double underscores to prefix the name. A Pythonic style is to use a single underscore to denote an attribute that should be treated as private and not directly accessed. But very often it's Python style to leave out any concept of setters and getters, instead just access them directly. Like this:

&gt;&gt;&gt; apple = Item('apple', 7.8)
&gt;&gt;&gt; print apple.name
apple
&gt;&gt;&gt; apple.price = 7
&gt;&gt;&gt; print apple.price
7


You could almost not have Item be a class, but your spec seems to require it so I wont suggest you change that.

Also you misspelled newitemprice as newitemprcie. You managed to make it consistent between the two (by copy pasting I assume) but keep an eye on little errors like that. They'll only cause headaches.

Your Cart is a little underdeveloped. All it does is subclass dict and then return itself when ShowCart is called? This is redundant since the Cart itself could be passed to places it's needed.

You mentioned in a comment you want to be able to do Cart['apple'] to get the count of apples, but an easier way to do that is to just have an attribute of cart that's a dictionary. For example:

class Cart:
    def __init__(self, items):
        self.items = items

Cart({"apple": 5, "pear": 7})
Cart.items["apple"]


This is a much clearer way to get at the items without needing to inherent a dictionary into the Cart itself.

Maybe the cart could more directly manage items so you could have useful features like counting how many of each item is there. As it stands, you don't do anything special with a cart that has multiple instances of the same item. Why not keep track of that so you could easier print to the user what they have, rather than expecting them to just read a list of items.

While we're on it. Why not implement a method or two to print the contents of a Cart nicer? Maybe the Cart should be where the user actually purchases things? You need to think about what a cart does, and create those functions.

Why make cartlist a dictionary? You should make it a list instead. You can still do cartlist.remove(cart_to_remove). Also don't name it cartlist especially if it's not a list, carts is better. Types don't need to be in names unless it's hard to tell what type a variable is.