I'm working on a simple product inventory which essentially allows user to add products, display them and deduce the inventory value. I am stuck in the part where the inventory value is deduced. What I want the code to do here is multiply the product price * product quantity for each added product and return the sum. When I run the code, I get the error, TypeError: 'int' object is not iterable. I am new at Python, would appreciate any guidance!
Here is a portion of the code:
class Product:
def __init__(self, idnum, price, quantity):
self.idnum = idnum
self.price = price
self.quantity = quantity
class Inventory:
def __init__(self):
self.productlist = []
def add_product(self):
idnum = int(input('Enter id: '))
price = int(input('Enter price: '))
quantity = int(input('Enter quantity: '))
self.productlist.append(Product(idnum, price, quantity))
return self.productlist
def display(self):
for product in self.productlist:
print(product.idnum, product.price, product.quantity)
def inventory_value(self):
for product in self.productlist:
return sum(product.price*product.quantity)
I think you meant to sum all the products (the result of multiplication) like that:
def inventory_value(self):
running_sum = 0
for product in self.productlist:
running_sum += product.price * product.quantity
return running_sum
Or simply:
def inventory_value(self):
return sum(product.price * product.quantity for product in self.productlist)
Notice that this `sums over a collection, and not a single integer, like in your case:
>>> [x * (x + 1) for x in range(5)]
[0, 2, 6, 12, 20]
>>> sum(x * (x + 1) for x in range(5))
40
Related
Create an object called Accounts. This is to be used in a banking system.
Initialize the account with three data as inputs : Firstname, Lastname and initial deposit.
Create 4 additional member functions: Deposit, Withdraw, Fee Calculations, interest
The fee calculation is going to be $10 per month if the total amount in the account is less than $1000. Interest is set to be at 3%.
I already got the code to work once, however it was with all the variables as integers, meaning none of them were decimals. Here's what I have now and I keep getting errors:
input = 'John Doe 4893.27'
account = str(input)
account = account.split()
first_name = account[0]
last_name = account[1]
i_deposit = account[2]
i_deposit = float(i_deposit)
i_deposit = '{:.2f}'.format(i_deposit)
new_amount = 0
fee = 0
d = 0
w = 0
def Deposit(d):
d = float(d)
d = '{:.2f}'.format(d)
d = bin(d)
new_amount = bin(i_deposit) + d
new_amount = bin(new_amount)
return bin(new_amount)
def Withdraw(w):
w = float(w)
w = '{:.2f}'.format(d)
w = bin(w)
new_amount = bin(i_deposit) + w
new_amount = bin(new_amount)
return bin(new_amount)
def FeeCalc(money):
money = float(i_deposit)
if money <= 1000:
fee = 10
else:
fee = 0
fee = '{:.2f}'.format(fee)
return fee
i = 0
def Interest(i):
i = float(i_deposit)
i = int(i)
i = i * .03
i = '{:.2f}'.format(i)
return i
dep_amount = Deposit(d)
wit_amount = Withdraw(w)
net_amount = sum(dep_amount, wit_amount)
new_amount = int(new_amount)
int_fee = Interest(i)
Withdraw(276.84)
print(first_name, last_name, 'account information:', '\nInitial deposit: $', i_deposit, '\nNew balance: $', new_amount, '\nFee: $', fee, '\nInterest: $', int_fee)
The most recent error I can't seem to fix:
Traceback (most recent call last):
File "/Users/shardae/PycharmProjects/HW1/main.py", line 55, in <module>
dep_amount = Deposit(d)
File "/Users/shardae/PycharmProjects/HW1/main.py", line 23, in Deposit
d = bin(d)
TypeError: 'str' object cannot be interpreted as an integer
Process finished with exit code 1
When you use the "'{:.2f}'.format(some_variable)" function, you are actually converting whatever variable you are assigning a value into a string. I don't believe that is what you after. With that, let me offer up some revision to your program that keeps the spirit of your code.
input = 'John Doe 4893.27'
account = str(input)
account = account.split()
first_name = account[0]
last_name = account[1]
i_deposit = float(account[2])
def Deposit(amount, d):
amount = amount + d
return amount
def Withdraw(amount, w):
w = (int(w) * 100) / 100 # Example of insuring precision to two decimal places
amount = amount - w
return amount
def FeeCalc(money):
fee = 0
if money <= 1000.00:
fee = 10
return fee
def Interest():
i = float(i_deposit)
i = int(i)
i = i * .03
return i
new_amount = i_deposit # Set the work field to the initial deposit balance
int_fee = Interest() # Calculate interest and add it to the balance
new_amount += int_fee
new_amount = Withdraw(new_amount, 276.84) # Calculate the new balance once the withdrawal amount is applied
fee = FeeCalc(new_amount) # Subtract any bank fee if the balance has dropped below $1000.00
new_amount -= fee
print(first_name, last_name, 'account information:', '\nInitial deposit: $', '{:.2f}'.format(i_deposit), '\nNew balance: $', '{:.2f}'.format(new_amount), '\nFee: $', fee, '\nInterest: $', int_fee)
The code still does utilize floating point variables. However, the only time that specific formatting for two decimal points occurs is within the printed output.
Go ahead and review the tweaks and see if that fulfills the spirit of your solution.
Hope that helps.
Regards.
I have a problem which is a simplified version of the knapsack problem. It goes like this. There is a store and we have a list of items in that store. Let's say like this,
Store has 2 types of products Normal products and limited products.
Product Class
class Product:
"""
A class to provide abstraction for products availabel in the system.
unless the product is a Limited_product its supply is infinite
"""
product_counter = 0
##### Part 1.1 #####
def __init__(self, name, price):
""" Constructor for initialization """
self.name = name
self.price = price
self.id = Product.product_counter
Product.product_counter += 1
def __str__(self):
""" returns a string representation of a product """
return "<{}> {} - {}$".format(self.id, self.name, self.price)
def __repr__(self):
""" represents the class object as a string """
return "PRODUCT <{}>".format(self.id)
Limited Product Class
class Limited_Product(Product):
"""
A child class of the parent Product class
Represents a Limited product where the quantity is depreceating
"""
##### Part 1.2 #####
def __init__(self, name, price, amount):
""" Constructor for initialization """
super().__init__(name, price)
self.amount = amount
def __str__(self):
""" returns a string representation of a limited product """
return "<{}> {} - {}$ ({} left)".format(self.id, self.name, self.price, self.amount)
def decrement_amount(self):
""" decrement the amount of available product """
self.amount -= 1
def get_amount(self):
""" returns the amount available from the product """
return self.amount
Now we are given a list of products and the maximum amount a customer can spend.
============================
Product - Price
A - 20$
B - 7$
C - 1$ (2 left)
============================
And we have to find out what is the minimum amount left after the customer buys a sequence from these items using both recursion as well as iteratively by completing the given two functions. These functions are given so I cannot write in a different method.
As an example:
>>> store.so_rich(45)
output - 1
You have 45 dollars to spend. The optimal solution is buying six B items and two C items. This will leave you with 45 - 7 * 6 - 1 * 2 = 1 dollars left. The least amount of money left is 1 since there is no way to spend all of the money. (although C’s price is 1$, you have purchased all of them already!)
>>> store.so_rich(61)
0
You have 61 dollars to spend. You can spend all of them by buying two A and three B (20 * 2 + 7 * 3 = 61). So the least amount of money left is 0.
The two functions that I wrote
def so_rich(self, money):
# suppose you haven't seen any product yet
# the only possible amount of money left is "money"
# this is a set to record the possible money left
left = set([money])
# get products
lst = list(self.warehouse.inventory.values())
print(str(lst))
for product in lst:
# a temporary set to save the updates of "left"
# you don't want to modify the set you're iterating through
tmp_left = set()
for m in left:
# update tmp_left
if type(product) != Limited_Product:
new_left = m
#new_left -= product.price
while product.price <= new_left:
print(new_left, product.name)
tmp_left.add(new_left)
new_left = new_left - product.price
else:
# handle limited product
new_left = m
product_count = product.amount
while product.price <= new_left and product_count > 0:
print(new_left, product.name)
tmp_left.add(new_left)
new_left = new_left - product.price
product_count -= 1
left = tmp_left
print(left)
return min(left)
def so_rich_recursive(self, money):
# get products
lst = list(self.warehouse.inventory.values())
def helper(lst, money):
# base case
if not lst:
return money
cur_min = money
product = lst[0]
if type(product) != Limited_Product:
tmp = money
while product.price < tmp:
cur_min = tmp
tmp -= product.price
print(cur_min, product.name)
else:
tmp = money
product_count = product.amount
while product.price <= tmp and product_count > 0:
cur_min = tmp
tmp -= product.price
product_count -= 1
print(cur_min, product.name)
money = money - cur_min
print("-----", money)
lst.pop(0)
return helper(lst, money)
return helper(lst, money)
I cannot understand why the above code written by me does not work. Can anyone help me, please?
I have a Category class and there is a ledger attribute for each instance of this class. This ledger attribute is actually a list of dictionaries which contain the withdrawal and deposit amounts and descriptions in the form {"amount" : amount, "description" : description}. Now, I want to define a function create_spend_chart which will take a list of objects as the parameter, and will find the total amount of withdrawals. I have been able to do this successfully:
def create_spend_chart(categories):
total_withdrawn = 0
for i in categories:
for p in i.ledger:
if p["amount"] < 0:
total_withdrawn += -p["amount"]
But the problem I'm facing here is, I can't seem to store the total withdrawal amount for each category object separately. How can I do this?
My code-base might help you ins answering the question:
class Category:
def __init__(self, name):
self.name = name
self.ledger = list()
def get_balance(self):
total_balance = 0
for i in self.ledger:
total_balance += i["amount"]
return total_balance
def check_funds(self, amount):
if self.get_balance() >= amount:
return True
else:
return False
def deposit(self, amount, description = "Deposit"):
form = {"amount" : int(amount), "description" : description}
self.ledger.append(form)
def withdraw(self, amount, description = "Withdrawal"):
if description == None:
description = "Withdrawal"
form = {"amount" : -int(amount), "description" : description}
if self.check_funds(amount):
self.ledger.append(form)
return True
else:
return False
def transfer(self, amount, category_object):
form1 = {"amount" : -int(amount), "description" : f"Transfer to {category_object.name}"}
form2 = {"amount" : int(amount), "description" : f"Transfer from {self.name}"}
if self.check_funds(amount):
self.ledger.append(form1)
category_object.ledger.append(form2)
return True
else:
return False
def __repr__(self):
Ledger = ""
for i in self.ledger:
if len(i["description"]) > 23:
des = i["description"][:23]
else:
des = i["description"]
Ledger += des.ljust(23) + str(round(i["amount"], 2)).rjust(7) + "\n"
Ledger = Ledger + "Total: " + str(round(self.get_balance(), 2))
receipt = f"{self.name}".center(30, "*") + "\n" + Ledger
return receipt
def create_spend_chart(categories):
total_withdrawn = 0
withdrawals = list()
for i in categories:
for p in i.ledger:
if p["amount"] < 0:
total_withdrawn += -p["amount"]
PS: This function is not a method, it is defined outside of the class declaration.
Use a collections.defaultdict to make aggregations such as that easy as pie.
import collections
# ...
withdrawn_per_category = collections.defaultdict(int)
for i in categories:
for p in i.ledger:
if p["amount"] < 0:
withdrawn_per_category[i.name] += -p["amount"]
(I've opted to use int as the default data type, but it doesn't truly matter here, so long as it's a conversible numeric type.)
Without collections
If for some reason you don't want to use the handy, built-in collections module, you can emulate the same behavior yourself with a regular dict:
withdrawn_per_category = {}
for i in categories:
for p in i.ledger:
if p["amount"] < 0:
withdrawn_per_category[i.name] = withdrawn_per_category.get(i.name, 0) - p["amount"]
Am trying to make a simple python program where we have to Create an application which manages an inventory of products.To create a product class which has a price, id, and quantity on hand. Then create an inventory class which keeps track of various products and can sum up the inventory value.
Please check the code below,
Input
import pandas as pd
class Product:
def __init__(self):
self.price = None
self.id = None
self.qty = None
self.data = pd.DataFrame(([]),columns=['ID','Cost','Quantity'])
class inventory(Product):
def value(self):
while True:
print("Please give your product details,")
self.cost = float(input("Cost of the product : "))
self.id = int(input("ID of the product : "))
self.qty = int(input("Quantity of the product : "))
print("==============================================================================")
self.data = self.data.append({'ID':self.id,'Cost':self.cost,'Quantity':self.qty},ignore_index=True)
print(self.data)
print("==============================================================================")
print("1)Would u like to add even more products?\n2)Get the inventory value\n3)Exit")
option = int(input())
if(option == 1):
inventory.value(self)
elif(option==2):
print("The total value of inventory is : ",((self.data['Cost'])*(self.data['Quantity'])).sum())
else:
print("Exiting....")
exit()
break
return
inv = inventory()
inv.value()
Output
Please give your product details,
Cost of the product : 10
ID of the product : 11
Quantity of the product : 12
==============================================================================
ID Cost Quantity
0 11.0 10.0 12.0
==============================================================================
1)Would u like to add even more products?
2)Get the inventory value
3)Exit
2
The total value of inventory is : 120.0
Please give your product details,
Cost of the product : 12
ID of the product : 12
Quantity of the product : 12
==============================================================================
ID Cost Quantity
0 11.0 10.0 12.0
1 12.0 12.0 12.0
==============================================================================
1)Would u like to add even more products?
2)Get the inventory value
3)Exit
3
Exiting....
After i press 2, am expecting my program to give me value and tell me, 1)Would u like to add even more products?2)Get the inventory value3)ExitHow do i do that? Also if u find any modifications or any suggestions, please let me know down below.
I personally would remove the while true loop and create functions to accomplish your task:
import pandas as pd
class Product(object):
def __init__(self):
self.price = None
self.id = None
self.qty = None
self.data = pd.DataFrame(([]),columns=['ID','Cost','Quantity'])
class inventory(Product):
# create a prod_detail function
def prod_detail(self):
print("Please give your product details,")
self.cost = float(input("Cost of the product : "))
self.id = int(input("ID of the product : "))
self.qty = int(input("Quantity of the product : "))
print("="*30)
self.data = self.data.append({'ID':self.id,'Cost':self.cost,'Quantity':self.qty},ignore_index=True)
print(self.data)
print("="*30)
self.option()
# create an options function
def option(self):
print("1)Would u like to add even more products?\n2)Get the inventory value\n3)Exit")
option = int(input())
if(option == 1):
self.prod_detail()
elif(option==2):
print("The total value of inventory is : ",((self.data['Cost'])*(self.data['Quantity'])).sum())
self.option()
else:
print("Exiting....")
exit()
def value(self):
# remove the while true loop and just run the prod_detail function
self.prod_detail()
inv = inventory()
inv.value()
Please give your product details,
Cost of the product : 1
ID of the product : 2
Quantity of the product : 3
==============================
ID Cost Quantity
0 2.0 1.0 3.0
==============================
1)Would u like to add even more products?
2)Get the inventory value
3)Exit
2 <--------
The total value of inventory is : 3.0
1)Would u like to add even more products?
2)Get the inventory value
3)Exit
Try this
import pandas as pd
class Product:
def __init__(self):
self.price = None
self.id = None
self.qty = None
self.data = pd.DataFrame(([]),columns=['ID','Cost','Quantity'])
class inventory(Product):
def value(self):
while True:
option = 1
if len(self.data):
print("1)Would u like to add even more products?\n2)Get the inventory value\n3)Exit")
option = int(input())
if option == 1:
print("Please give your product details,")
self.cost = float(input("Cost of the product : "))
self.id = int(input("ID of the product : "))
self.qty = int(input("Quantity of the product : "))
print("==============================================================================")
self.data = self.data.append({'ID':self.id,'Cost':self.cost,'Quantity':self.qty},ignore_index=True)
print(self.data)
print("==============================================================================")
inventory.value(self)
elif option == 2:
print("The total value of inventory is : ",((self.data['Cost'])*(self.data['Quantity'])).sum())
else:
print("Exiting....")
exit()
inv = inventory()
inv.value()
I'm having trouble entering data I keep getting the error "invalid literal for int() with base 10"
def strings_to_ints(linelist):
outputlist = []
for item in linelist:
outputlist.append(int(item))
return outputlist
def process_line(line):
global box_count, ship_class
linestrings = line.split()
name = linestrings[0]
linevalues = strings_to_ints(linestrings[:1])
quantity = linevalues [0]
ship_class = linevalues [1]
box_count = box_count + quantity
order_price = compute_price(quantity)
discounted_price = compute_discounted_price()
tax = compute_tax(discounted_price)
ship_cost = compute_ship_cost(quantity)
billed_amount = discounted_price + tax + ship_cost
outlist = [quantity, order_price, compute_discount(), tax, ship_cost, billed_amount]
return name, outlist
def enter_data():
global order_count
line = input('Enter Name, Quantity, and Ship Class: >>> ')
name, outlist = process_line(line)
order_count = order_count + 1
print(name, outlist))
I know I that the name should somehow be separate from the numbers but I can't figure out where to do this.
I added the most of code, all of the relevant parts I think. Hopefully, it's easier to understand
linevalues = strings_to_ints(linestrings[:1])
should be:
linevalues = strings_to_ints(linestrings[1:])
Assuming that both Quantity and ship class are integers, and are space separated
i.e.
Test 1 2
Whithout understanding all of your code, I think that the problem is that linestrings[:1] is an array containing at most the first element of linestrings. If you want all but the first, use linestrings[1:] instead.