Tuple error with class and object - python

I'm currently working on this,
Design a class Car.
This class has the following attributes: maker, model, and price
The Car class should have methods to return the current values of these attributes. In addition, this class has a method update_price to change the price attribute value.
Design a class called Dealer.
This class has the following attributes: address and inventory. The inventory attribute is a list of Car objects.
The Dealer class should have methods to add a car object to the inventory, remove a car object from the inventory (car removal should be done based on car model), and update the price of a certain car model. This class also has a method that shows the entire inventory and a method that calculates the total value of all cars in the inventory.
In the main function, the program creates a Dealer object, adds multiple cars to the inventory, and shows the current inventory. Then the program removes a car model from the inventory and updates the price for a given car model. At the end, the program displays the entire inventory and the total value of all cars currently in the inventory.
But when I run my code I get
TypeError: descriptor 'append' requires a 'list' object but received a 'tuple'
And I have no idea how to fix this
class Car:
def __init__(self, maker, model, price):
self.__maker=maker
self.__model=model
self.__price=price
def get_model(self):
return self.__model
def get_maker(self):
return self.__maker
def get_price(self):
return self.__price
def create_list(list):
maker=input('Enter Car maker: ')
model=input('Enter Car model: ')
price=float(input('Enter Car price: $'))
account=(maker, model, price)
list.append(account)
def update_price(self):
self.__price=price
return self.__update_price
class Dealer():
def __init__(address, inventory):
self.__inventory=inventory
self.__address=address
def update_price(list):
model=input('Enter car model: ')
account=Car(maker, model, price)
found='false'
for model in list:
if account.get_model() == model:
account.append(price)
found=='true'
if found == 'false':
print('Model Not Found')
return account
def show_inventory(list):
show_inventory=print(account)
def calculate_total_value(list):
print(sum(self.__account.price))
def remove_car(list):
model=input('Model for removal')
found = 'false'
for model in list:
if account.get_model() ==model:
account.remove(model)
found =='true'
if found =='false':
print('Model Not Found')
def get_address(address):
self.__address=address
return self.__address
def main():
address=input('Enter address: ')
account_list=[]
counter=1
manytimes=float(input('How many cars to add? '))
while counter<=manytimes:
counter=counter+1
create_list(list)
show_inventory(account_list)
remove_car(account_list)
show_inventory(list)
update_price(account_list)
show_inventory(account_list)
calculate_total_value(account_list)
main()

Looks like wherever that error is occuring, you're trying to append something to a tuple which is immutable, meaning it can't be changed (in this case, you can't append something to it). A tuple is very similar to a list in that in can store values and be accessed through an index (starting at 0). Wherever you're trying to append something, make sure you're using a list and not a tuple. If it is a tuple, you can convert it to a list using list(tuple_name) and then you should be able to append to it.

Related

Attribute not defined error, even though it is defined on a global scope

I'm a newbie to python so please bear with me. I was making a class that contains the make, model, and fuel of a car and was experimenting with the set and get methods to try and learn their use. The issue I'm running into is when I try to update my tank attribute by running my setFuel method and print out the updated fuel integer I get the error tank is not defined even though I defined it all the way above. Why is this occurring and how can I fix it?
I added comments all over my code to explain what I tried to do to help you understand my code. Any help is appreciated thanks in advance.
class Car:
tank = 0 #to keep track of fuel
make = ""
model = "" #to keep track of model
def __init__(self, make, model, fuel):
self.make = make
self.model = model
self.fuel = fuel
#returns the amout of fuel currently in the tank(as an integer)
def getFuel(self):
return int(self.fuel)
#sets the amounts of fuel currently in the tank(as an integer)
def setFuel(self, tank):
self.tank = int(tank)
#returns the make and model of the car as a string
def getType(self):
return str(self.make),(self.model)
def printFuel(self):
print(self.fuel)
#Instantiate a new Car in a variable
myCar = Car("Ford", "Escort", 10)
yourCar = Car("Ford", "Escape", 14)
#print statement that prints the result of the "getFuel"
#method of the "myCar" object
myCar.printFuel()
yourCar.printFuel()
#Change the "tank" attribute to modify the fuel in the tank using
#setFuel method of the "myCar" and "yourCar" object
#subtract 7 from from the tank
myCar.setFuel(tank-7)
#subtract 5 from the tank
yourCar.setFuel(tank-5)
#print statement that prints the result of the "getFuel"
#method of the "myCar" and "yourCar" object
print(myCar.getFuel())
print(yourCar.getFuel())
print(myCar.getType())
print(yourCar.getType())
Doing this:
class Car:
tank = 0
make = ""
model = ""
tank, make, and model are class variables shared by all instances, so myCar and yourCar will share the same tank. Read the Python doc for more details about Class and Instance Variables.
Because the tank of a car is part of every car (every instance) is better to use instance variables. So is better to write these vars inside __init__:
class Car:
def __init__(self, make, model, fuel):
self.tank = 0
self.make = make
self.model = model
self.fuel = fuel
Now, tank is an instance variable. To access it, use myCar.tank (here myCar is an instance of the object Car). So, to subtract fuel from the tank do:
myCar.setFuel(myCar.tank - 7)
EDIT: Your code is not reducing the fuel when you print it because you have another problem with your code. Look at your setFuel function, it is setting the tank and not the fuel. Change to:
def setFuel(self, fuel):
self.fuel = int(fuel)
Also when you set the fuel in myCar, you are using myCar.tank - 7 where tank is equal to 0. So what you need is to do is:
myCar.setFuel(myCar.fuel - 7)
I think a better idea will be to make a function inside the Car object to reduce the fuel, and in this function check if the Car has enough fuel (because you cant'n have -x fuel, right?), like this:
def reduceFuel(self, fuel_used):
if self.fuel - fuel_used < 0:
raise ValueError("Not enough fuel")
else:
self.fuel -= fuel_used
and to use:
myCar.reduceFuel(7)
You need myCar.setFuel(myCar.tank-7) and yourCar.setFuel(yourCar.tank-5). You might consider adding a useFuel method to make that easier.

How to get a total from with "Class" in python, then calling it into another file main()?

My assignment is : Assume you sell t-shirts ( or any other item), and all t-shirts cost the same, they all have the same price
Define a class called Sale. The first line of the constructor would only have 3 arguments: self, item and quantity. In addition, the constructor has an attribute for the price and an attribute to hold the total for the sale.
The program assumes the same price for every item, so you can initialize the price in init using the price of your choice. Just like we did with the car example I showed in the lecture, where the speed attribute was initialized to zero in init, you could initialize total at total to zero
The class should have 4 methods to:
A method to calculate the total
A method to return the total
A method to return the item
A method to return quantity
The program importing the file with this class needs to create an instance of the Sale class. Assuming, the file with the class definition is sale.py and the class is Sale, it would look something like this
new_sale = sale.Sale('Men medium blue', 10)
When I run the program that creates the class instance, assuming the price in the class was set to 9.99, the output would look something like this
new_sale = sale.Sale('Men medium blue', 10)
The total for 10 t-shirts Men medium blue is $ 99.9
'''class Sale:
def __init__(self,item,quantity):
self.item=item
self.quantity=quantity
self.total=self.price*self.quantity
self.price=10
def get_item(self):
return self.item
def get_quantity(self):
return self.quantity
def get_total(self):
return self.total
'''
This is my main function in another file, I'm trying to get the user input quantity to multiply by the set price ($10) in Class
'''
import sale
def main():
itemQ=input("Please enter type of t-shirt: ")
quanT=int(input("Please insert number of t-shirt you wish to buy: "))
theSale= sale.Sale(itemQ, quanT)
print("The item is ", theSale.get_item(), " and a quantity of ", theSale.get_quantity(), "and total of ", theSale.get_total())
main()
'''
A couple minor changes should get it working:
# sale.py
def __init__(self, item, quantity):
self.item=item
self.quantity=quantity
self.price=10
self.total=self.price*self.quantity # you have to define price before you use it to calculate the total
# add these two lines at the end of you main .py file
if __name__ == '__main__':
main()
See python docs on main method: main

Code is looking for attributes in the wrong class

This code's really unfinished, but it's getting there. I'm trying to organize the inputs of an item's name and price to a list, but I'm getting an error caused by the code looking for the _purchases attribute in the Item class instead of the Receipt class. What's causing this?
import datetime
class Item:
def __init__(self,_name="None",_price=0,_taxable="no"):
self._name=_name
self._price=_price
self._taxable=_taxable
def __str__(self):
base="{:-<20}".format(self._name)+"{:->20}".format(self._price)
return base
def getPric(self):
pass
def getTax(self):
pass
class Receipt:
def __init__(self,_tax_rate=0,_purchases=""):
self._tax_rate=_tax_rate
self._purchases=_purchases
def __str__(self):
pass
def additem(self):
list=self._purchases.append(self)
#Main Program
if __name__=="__main__":
loop="no"
print("Welcome to Receipt Creator")
while True:
name=input("Enter Item name: ")
price=float(input("Enter Item Price: "))
taxable=input("Is the item taxable (yes/no): ")
product=Item(name,price,taxable)
print(product)
print(Receipt.additem(product))
print(list)
loop=input("Add another item (yes/no): ")
if loop=="yes":
continue
else:
break
print("----- Receipt",str(datetime.datetime.now()),"-----")
print(list)
EDIT: Here's the error
Traceback (most recent call last):
File "C:\Users\lucas\Desktop\main.py", line 35, in <module>
print(Receipt.additem(product))
File "C:\Users\lucas\Desktop\main.py", line 23, in additem
list=self._purchases.append(self)
AttributeError: 'Item' object has no attribute '_purchases'
You have a clear idea of what you have, but the execution has a lot of room for improvement.
Let's not touch the Item class, since that is not the one that is causing troubles. But as regards to Receipt, let's create a list for purchases to hold the purchases, and let's define a method (add_item) to populate that list:
class Receipt:
def __init__(self, tax_rate=0):
self.tax_rate = tax_rate
self.purchases = []
def add_item(self, item):
self.purchases.append(item)
Now, you definitely need to instantiate that Receipt class (as opposite as you were doing), so in your main loop you should have something like:
if __name__=="__main__":
print("Welcome to Receipt Creator")
rcpt = Receipt()
while True:
name = input("Enter Item name: ")
price = float(input("Enter Item Price: "))
taxable = input("Is the item taxable (yes/no): ")
product = Item(name, price, taxable)
print(product)
rcpt.add_item(product)
print(rcpt.purchases)
loop = input("Add another item (yes/no): ")
if loop == "yes":
continue
else:
break
print(rcpt.purchases)
Now, some things to note in your previous code:
Unless you want to let other people know that an attribute is meant to be used only inside the definition of a class, there's no actual need to use a leading underscore to name an attribute.
You were trying to print list. Keep in mind that list is a builtin class, so try name your attributes using something different (you can use a trailing underscore, actually. Like list_). Moreover, you were trying to print the list attribute that you had defined in your additem() method, without having instantiated the Receipt class and ask the class for it (with something like instance.list_).
In your __init__ method of the Receipt class that you had defined, you had a default value for _purchases to be "" (an empty string), but that attribute was intended to be a list. (since you were trying to use the append() method after in your additem() method), which makes no sense at all.
#revliscano has an answer that fixes your issues. I will leave the answer to him. I am just going to explain why you got the somewhat confusing error that you got.
looking for _purchases attribute in the Item class
In your class Receipt you have:
class Receipt:
...
def additem(self):
list=self._purchases.append(self)
and were later calling it with:
product=Item(name,price,taxable)
print(product)
print(Receipt.additem(product))
So you are calling additem() on the Receipt class, not on an instance of that class. Normally when you call an instance method, the instance you are calling it with is passed in as the self by python. It did not have an instance since you called it on the class itself, and as a result under the hood python was passing the product in as the self variable because python was treating it like a call on a static class method though it was supposed to be an instance method (i.e. no cls or self arg, and just pass the given arg to the method). So because you called it like Receipt.additem(product), the product was passed as the self.
That meant that when it tried to do the self._purchases.append(self) it was like it was trying to do product._purchases.append(product) and so it was trying to find the _purchases attribute on product. Since product is an instance of the Item class, that is how you get your confusing error message.

My code isn't working when I call the methods from Retail Class

I'm trying to display the information from the following methods but its not displaying. This based on question below. Also, I changed the names of the units inventory.
Write a class named that holds data about an item in a retail store. The class should RetailItem store the following data in attributes: item description, units in inventory & price.
Once you have written the class, write a program that creates three objects and RetailItem stores the following data in them:
Description Units in Inventory Price Item
Item #1 Jacket 59.95
Item #2 Designer Jeans 34.95
Item #3 Shirt 20 24.95
class Retail_Item:
def __init__(self, item_description, units_in_inventory, price):
self.item_description = item_description
self.units_in_inventory = units_in_inventory
self.price = price
def item_description(self):
return self.item_description
def units_in_inventory(self):
return self.units_in_inventory
def price(self):
return self.price
import retail_items
def main():
retail=retail_items.Retail_Item("Jacket","12","59.95")
retail_2=retail_items.Retail_Item("GUCCI","14","34.95")
retail_3=retail_items.Retail_Item("LEVIS","15","24.95")
print("Description:",retail.item_description())
print("Price:",retail.units_in_inventory())
print("Units in Inventory:",retail.price())
print()
print("Description:",retail_2.item_description())
print("Price:",retail_2.units_in_inventory())
print("Units in Inventory:",retail_2.price())
print()
print("Description:",retail_3.item_description())
print("Price:",retail_3.units_in_inventory())
print("Units in Inventory:",retail_3.price())
main()
You get an error because, for example, the method and member variable "item_description" both have the same name. Python cannot dinstinguish both. Therefore by calling item.item_description() you try to call the member variable like a function, which is not possible (Python tells you that via "str object is not callable").
3 possible solutions:
You could rename your member variables to e.g. m_item_description. That way python can distinguish both.
Rename the Get-Method to e.g ItemDec()
Don't use a Get-Method at all, but access the member variable directly via item.item_description (don't use braces)

How to access a class object and its attributes from user input?

I just started programming and I decided to use Python for my first attempts at coding, and I am now practicing with classes and objects.
I apologize if the question I am about to ask has been asked before, but I can't seem to find answers anywhere, so here it goes.
I have a file that contains a class. Below the full code I have written :
#class file
#class prodotti refers to "register" with products in stock and their prices
class Prodotti(): #class Prodotti() contains products from register and their relative specs
def __init__(self, nome="", #name of product
prezzo=0, #product price
quantità=0,): #stock quantity of product
self.nome=nome
self.prezzo=prezzo
self.quantità=quantità
def newproduct(self): #method appends new product and its specs to the end of this file
name=input("Inserire nuovo prodotto: ")
f=open("cassa3.py", "a")
f.write(name + "=Prodotti(nome='" + name + "', ")
price=input("Inserire prezzo prodotto: ")
f.write("prezzo=" + price + ", quantità=0)\n")
f.close()
def tellprice(self): #method should return price of object
inp=input("Di quale prodotto vuoi conoscere il prezzo? ") #asks user which product they want to know the price of
if inp=Prodotti():
print(inp.prezzo)
#class objects
#user can insert new products that are saved below
tortino=Prodotti(nome="Tortino al cioccolato", prezzo=3.4, quantità=0)
muffincioccolato =Prodotti(nome="Muffin al cioccolato", prezzo=1.8, quantità=0)
cupcake=Prodotti(nome='cupcake', prezzo=2, quantità=0)
In another file, saved in the same directory, I have the main program:
from cassa3 import Prodotti #file cassa3.py in same directory as this file
if __name__=="__main__":
P=Prodotti()
P.tellprice()
As you may tell from the code above, what I want method tellprice() to do is to ask the user what product they want to know the price of.
However, I just don't know how to make the user input correspond to a class object, so that I can access its attributes.
Can someone explain how i could manage to do that?
Thanks in advance.
Before you will be able to solve this issue, you will need to fix the design problem you have.
Your comment says # class Prodotti() contains products from register and their relative specs but it is not quite true. This class contains a single product with its name, price and quantity.
You will need to define another class (perhaps Register) that will actually store a list (or dictionary if product names are unique for efficient lookup, or whatever) of products (instances of Prodotti).
The tellprice method currently makes no sense. It simply creates a new instance of Prodotti and the if condition will never be True.
Also, it is highly suggested to use English names in code.
Consider the below example as a general guide:
class Product:
def __init__(self, name, price, quantity):
self.name = name
self.price = price
self.quantity = quantity
# (... some other methods ... )
class Register:
def __init__(self, products):
# this will store the products in a dictionary with products names as keys
# and Product instances as values for an efficient look up by tell_price
self.products = {product.name: product for product in products}
def tell_price(self):
name = input('Which product would you like to know the price of?')
# this will raise KeyError if user inputs a non-existing product name
# and should be caught, or use .get(...) instead
return self.products[name].price
apple = Product('apple', 1, 10)
banana = Product('banana', 2, 2)
register = Register([apple, banana])
print(register.tell_price())
# Which product would you like to know the price of?
>> apple
# 1
I wouldn't make your tellprice include user input.
def tellprice(self): #method should return price of object
return self.price
Then in main (this is significantly simplified):
inp = input("Di quale prodotto vuoi conoscere il prezzo? ")
print(inp.tellprice)
Obviously this assumes they put in the correct product name, so some way of indicating to the user that they're incorrect might be useful

Categories