1

method remove_item that requires similar arguments as add_item. It should remove items that have been added to the shopping cart and are not required. This method should deduct the cost of these items from the current total and also update the items dict accordingly. If the quantity of items to be removed exceeds current quantity in cart, assume that all entries of that item are to be removed.

class ShoppingCart(object):
#constructor
def __init__(self):
    self.total = 0
    self.items = {}

#method to add items in the shoping cart
def add_item(self,item_name, quantity, price):
    self.total += (price * quantity )
    self.items[item_name] = quantity

#method to remove items
def remove_item(self,item_name, quantity, price):
    keys = self.items.keys()
    for keys,v in self.items.items():
    if keys == item_name and quantity > self.items[keys]: #if item_name equals iterated item 
        self.total -= (price * quantity )
        del( self.items[keys] )
    del(self.items[keys])
    self.total -= (quantity * price)

And there are test units to check

def test_add_item_hidden(self):
    self.cart.add_item('Mango', 3, 10)
    self.cart.add_item('Orange', 16, 10)
    self.assertEqual(self.cart.total, 190, msg='Cart total not correct after adding items')
    self.assertEqual(self.cart.items['Orange'], 16, msg='Quantity of items not correct after adding item')

The method remove_item gives an error that dictionary changed size during iteration even after trying to access via keys as shown above

Shammir
  • 927
  • 4
  • 17
  • 32
  • 1
    `.keys` and `.items` return a *view*. Use `list` on them to get an independent iterable object. – juanpa.arrivillaga Jul 26 '17 at 22:01
  • Error is because you are modifying dictionary(deleting items) during iteration. Try to store keys to temp list like "keys_to_delete" during iteration(in for loop) and delete later. Refer https://stackoverflow.com/questions/10665591/how-to-remove-list-elements-in-a-for-loop-in-python – Akshay Jul 26 '17 at 22:07
  • 2
    What juanpa.arrivillaga said. BTW, `del` isn't a function, so don't write it like a function. Get rid of those parentheses. – PM 2Ring Jul 26 '17 at 22:11
  • @PM2Ring wow! didn't know this good practice. Thanks for sharing. – Akshay Jul 26 '17 at 22:14
  • No worries. I just had a closer look at your code and noticed that your remove_items method has a few problems. It doesn't need to iterate over the whole dict. It should either update the quantity of the named item, or delete that item from the dict. – PM 2Ring Jul 26 '17 at 22:31

1 Answers1

3

I think the remove_item function could be more simple.

#method to remove items
def remove_item(self,item_name, quantity, price):
    if item_name in self.item.keys():
        self.total -= (price * quantity)
        del self.items[item_name]

With this version, you are checking if item_name is on the dictionary, and if so, you are removing it, and removing the price from total

Trying to remove from a dict,list,typle while iterating over them, is not usually a good idea.

If item_name is a list of keys, I have to suppose that quantity and price are too. so a possible function could be:

def remove_item(self,item_name, quantity, price):
    for index, value in enumerate(item_name):
        if value in self.item.keys():
             self.total -= (price[index] * quantity[index])
             del self.items[value]

I haven't tested but should work.


if the idea is to get an inventory of the items. The function should be something like this.

#method to remove items
def remove_item(self,item_name, quantity, price):
    if item_name in self.items.keys():
        #remove from total the price for the items
        if quantity <= self.items[item_name]:
             self.total -= (price * quantity)
        else:
             self.total -= (price * self.items[item_name])
        #if quantity is greater or equal of the current value, item is removed.
        if quantity >= self.items[item_name]
            del self.items[item_name]
        else:
            self.items[item_name] -= quantity