-2

I'm trying to complete a lab on OOP in Python.
The assignment consists of creating a ‘ShoppingCart’ and ‘Shop’ class with ‘Shop’ inheriting from ‘ShoppingCart’.

In the Shopping Cart class is a constructor that takes no arguments and sets the ‘total’ attribute to zero and initializes an empty dict attribute named ‘items’.
Also the following methods are to be created ‘add_item’, ‘remove_item’ (both requiring similar arguments: item_name, quantity, price); the ‘add_item’ method should add the cost of the added items to the current value of total and also add an entry to the ‘items’ dict such that the key is ‘item_name’ and value is ‘quantity’ while the ‘remove_item’ method does the reverse; and a ‘checkout’ method that takes in ‘cash_paid’ and returns the balance from the payment

The ‘Shop’ class has a constructor that takes no arguments and initializes an attribute ‘quantity’ at 100.
It is also required to override the ‘remove_item’ method such that calling Shop’s ‘remove_item’ with no arguments decrements quantity by one.

I keep getting a stack trace error relating to the super method in the 'Shop' class.

Here's my code so far:

class ShoppingCart:

   def __init__(self):
      self.total = 0
      self.items = {}

   def add_item(self, item_name, quantity, price):
      self.price = price
      self.item_name = item_name
      self.quantity = quantity
      if self.item_name in items:
        items[item_name] += quantity
      else:
        items[item_name] = quantity
      self.total += price*quantity

   def remove_item(self,item_name, quantity, price):
      self.price = price
      self.quantity = quantity
      self.item_name = item_name
      if self.item_name in items:
        self.total -= price*quantity
        del items[item_name]

   def checkout(self, cash_paid):
      self.cash_paid = cash_paid
      if cash_paid < self.total:
        return "Cash paid not enough"
      else:
        return cash_paid - self.total

class Shop(ShoppingCart):
   def __init__(self):
      super().__init__(quantity)
      self.__quantity = 100

   def __remove_item (self):
      self.__quantity -= 1

Also my add_item and remove_item methods seem to raise errors, but I don't know what I'm doing wrong.

These are the unit tests for the lab, it's really challenging:

import unittest

class ShoppingCartTestCases(unittest.TestCase):
  def setUp(self):
    self.cart = ShoppingCart()
    self.shop = Shop()

  def test_cart_property_initialization(self):
    self.assertEqual(self.cart.total, 0, msg='Initial value of total not correct')
    self.assertIsInstance(self.cart.items, dict, msg='Items is not a dictionary')

  def test_add_item(self):
    self.cart.add_item('Mango', 3, 10)

    self.assertEqual(self.cart.total, 30, msg='Cart total not correct after adding items')
    self.assertEqual(self.cart.items['Mango'], 3, msg='Quantity of items not correct after adding item')

  def test_remove_item(self):
    self.cart.add_item('Mango', 3, 10)
    self.cart.remove_item('Mango', 2, 10)

    self.assertEqual(self.cart.total, 10, msg='Cart total not correct after removing item')
    self.assertEqual(self.cart.items['Mango'], 1, msg='Quantity of items not correct after removing item')

  def test_checkout_returns_correct_balance(self):
    self.cart.add_item('Mango', 3, 10)
    self.cart.add_item('Orange', 16, 10)

    self.assertEqual(self.cart.checkout(265), 75, msg='Balance of checkout not correct')
    self.assertEqual(self.cart.checkout(25), 'Cash paid not enough', msg='Balance of checkout not correct')

  def test_shop_is_instance_of_shopping_cart(self):
    self.assertTrue(isinstance(self.shop, ShoppingCart), msg='Shop is not a subclass of ShoppingCart')

  def test_shop_remove_item_method(self):
    for i in range(15):
      self.shop.remove_item()
      self.assertEqual(self.shop.quantity, 85)
LordNero
  • 11
  • 3

1 Answers1

0

I keep getting a stack trace error relating to the super method in the 'Shop' class

Maybe because...

In the Shopping Cart class is a constructor that takes no arguments

And you're trying to pass quantity as an argument to a no-arg constructor

Besides, quantity is an undefined variable there


Additionally, why would a shopping cart have a singular item name? Or only be the size/price of the lastly added or removed item?

def add_item(self, item_name, quantity, price):
    self.price = price
    self.item_name = item_name
    self.quantity = quantity

def remove_item(self,item_name, quantity, price):
    self.price = price
    self.quantity = quantity
    self.item_name = item_name

I think you want an Item class, and your Cart holds a list of those, not a dictionary

Reason being: You have a dictionary that can only hold singlular keys. As soon as you delete just one items[item_name], regardless of "quantity", you empty all items with that name.

OneCricketeer
  • 126,858
  • 14
  • 92
  • 185
  • Isn't self.items = {} the right syntax to creating an empty dict? – LordNero Apr 11 '17 at 16:52
  • That creates an empty `set`. If you want a dict explicitly, you would use `dict()`. Functionally, there is little different, though – OneCricketeer Apr 11 '17 at 16:56
  • there's no literal for an empty set, items = {} will be a dict, but items = {1, 2 .., } will be a set. (unless something has changed in python 3.x) – chatton Apr 11 '17 at 17:05
  • I have refactored my code with the various suggestions, now I'm getting a keyerror(mango, ) – LordNero Apr 11 '17 at 17:12
  • Maybe that's because your "unit-tests" are poorly written... `self.cart.remove_item('Mango', 2, 10)`... `self.assertEqual(self.cart.items['Mango']`... That key doesn't exist! – OneCricketeer Apr 11 '17 at 17:50