I am trying to decorate my instance car_details with another instance method decor but am not able to figure out why this is giving the error. while i call the call car_details method like below
if __name__ == '__main__':
car_type = input("Enter type of car: ")
price = int(input("Enter price of car: "))
obj = Car(car_type, price)
decor = obj.decor
details = obj.car_details
tax = {1: "Yes", 2: "No"}
to_apply = int(input("Select 1 for applying tax and 0 for No:"))
ans = tax.get(to_apply)
res = decor(details)
res(ans)
then it works properly, but while i try it with the #decorator at that time i get issue.
TypeError: decor() missing 1 required positional argument: 'func'
TYPE = {'hybrid': 'Hybrid', 'petrol': 'Petrol', 'deasel': 'Deasel'}
def tax_price(car_type):
if car_type == 'hybrid':
SGST = 300000
GST = 500000
elif car_type == 'petrol':
SGST = 200000
GST = 400000
elif car_type == 'deasel':
SGST = 100000
GST = 300000
return SGST+GST
class Car:
def __init__(self, car_type, price):
self.car_type = car_type
self.price = price
def decor(self, func):
def wrapper(apply_tax):
if apply_tax == 'Yes':
car_tax = tax_price(self.car_type)
self.price += car_tax
func()
else:
func()
return wrapper
#decor
def car_details(self):
print("Car Type:", self.car_type)
print("Car Price: ", self.price)
if __name__ == '__main__':
car_type = input("Enter type of car: ")
price = int(input("Enter price of car: "))
obj = Car(car_type, price)
tax = {1: "Yes", 2: "No"}
to_apply = int(input("Select 1 for applying tax and 0 for No:"))
ans = tax.get(to_apply)
wrp = obj.car_details()
wrp(ans)
I see a few problems here. The biggest problem is you seem to be trying to use a decorator when a decorator is really (and I mean really) not suitable for this situation. If this code is not experimental and is to be maintained by someone, I strong suggest simplifying to:
def car_details(self, apply_tax):
if apply_tax == 'Yes':
car_tax = tax_price(self.car_type)
self.price += car_tax
print("Car Type:", self.car_type)
print("Car Price: ", self.price)
But if you are just experimenting and want to make it work with decorators, I see the following problems:
When a decorator is called, the only arg passed to it is the function being decorated, not self which is not passed in at all. That means def decor(self, func): will need to change to def decor(func):.
When the decorated function, which is a method of a class, is invoked, the first arg will be self. That means def wrapper(apply_tax): will need to change to def wrapper(self, apply_tax):.
When the wrapped functions is invoked, it needs self as its only arg. That means func() will need to change to func(self) (in both places).
So, that gives:
def decor(func):
def wrapper(self, apply_tax):
if apply_tax == 'Yes':
car_tax = tax_price(self.car_type)
self.price += car_tax
func(self)
else:
func(self)
return wrapper
But, how does the decorated function get a value for apply_tax? It needs to be passed as an arg. So, you'll need ...
wrp = obj.car_details(ans)
Since this is a call on an instance, Python will automatically add self as the first arg and since car_details is decorated it will effectively be calling wrapper(self, ans).
Related
class Satellite:
def __init__(self, message):
print(message)
self.name = input("name: ").title()
self.lbs = int(input("lbs: "))
self.speed = int(input("speed: "))
lstSat = []
e= input("Would you like to create satellites? If yes, type O. If not, type another letter: ").lower()
i=0
while e=="o":
lstSat.append(Satellite("Info for satellite "+str(i+1)))
i+=1
e= input("Type O to create another satellite: ").lower()
Hello,
How can I make sure that 2 Satellites cannot be the same?
Please don't ask for user input during class construction. Much better to acquire the values elsewhere then use a straightforward constructor based on the user's input values.
In order to determine repetition, you need to override the eq dunder method.
Try this:
class Satellite:
def __init__(self, name, lbs, speed):
self._name = name
self._lbs = lbs
self._speed = speed
def __eq__(self, other):
if isinstance(other, str):
return self._name == name
if isinstance(other, type(self)):
return self._name == other._name
return False
def __str__(self):
return f'Name={self._name}, lbs={self._lbs} speed={self._speed}'
lstSat = []
PROMPT = 'Would you like to create satellites? If yes, type O. If not, type another letter: '
while input(PROMPT) in 'Oo':
name = input('Name: ').title()
if name in lstSat:
print(f'{name} already in use')
else:
lbs = int(input('lbs: '))
speed = int(input('Speed: '))
lstSat.append(Satellite(name, lbs, speed))
for satellite in lstSat:
print(satellite)
I would go for iteration in list and check names with every satellite
...
while e=="o":
satellite = Satellite("Info for satellite " + str(i+1))
if check_reapeated_name(lstSat, satellite.name): # see definition of function bellow
lstSat.append(satellite)
else:
# here do some output or error handling
...
...
and the definition of check_reapeated_name() would be something like this:
def check_reapeated_name(lstSat, satellite_name):
for i in lstSat:
if i.name == satellite_name:
return False
return True
I'm working on a project for CS1410, where I need to simulate a Coffee Machine. I have quite a bit so far, but I'm a bit stuck, specifically with these questions:
In the class CashBox, under the function deposit, I'm trying to add the values together from any coins inserted in the oneAction function from the CoffeeMachine class. However I get the error "'CoffeeMachine' object has no attribute 'credit'" and I'm struggling with understanding why. I can tell it's an inheritance problem, but I'm unsure exactly how to fix it.
How should I format it so that when I get the input in oneAction(), I can take that input and mess with it in the cashBox? What am I doing wrong with self.something, and how can I recognize when to use self, and when to just use a normal variable
I wasn't sure how to upload the code so that the problem is reproducible without giving at least this file, it's all pretty tied together. Some advice on how I could have presented this better would be helpful as well.
Past the original question, any further advice would be seriously appreciated.
Seriously.
Thank you all, hopefully the code is pretty readable.
class CashBox(object):
def __init__(self):
self.credit = 0
self.totalReceived = 0.0
def deposit(self,amount):
self.credit = amount + self.credit
self.totalReceived = amount + self.totalReceived
print(self.totalReceived,self.credit)
def returnCoins(self):
print("Returning ", self.totalReceived, " cents.")
self.totalReceived = 0.0
def haveYou(self,amount):
return self.credit >= amount
def deduct(self,amount):
pass
def totalCoins(self):
return self.totalReceived
class CoffeeMachine(object):
def __init__(self):
self.cashBox = CashBox()
self.selector = self.cashBox
def oneAction(self):
while True:
command = input("""
______________________________________________________
PRODUCT LIST: all 35 cents, except bouillon (25 cents)
1=black, 2=white, 3=sweet, 4=sweet & white, 5=bouillon
Sample Commands: insert 25, select 1. Your command:
""")
words = command.lower().split()
if 'select' in words:
Selector.select(self,int(words[1]))
print("Great selection!")
elif 'insert' in words:
coinsAllowed = [5,10,25,50]
if int(words[1]) in coinsAllowed:
CashBox.deposit(self,int(words[1]))
else:
print("""
That is not one of the allowed coins,
please insert a penny, nickel, dime, quarter,
or half-dollar. Thank you.
""")
elif 'cancel' in words:
print("Cancelling transaction. Returning to main menu: ")
CashBox.returnCoins(self)
elif 'quit' in words:
print("Have a nice day!")
else:
print("That is not an option")
def totalCash(self):
pass
class Product(object):
def __init__(self,name,price,recipe):
self.name = name
self.price = price
self.recipe = recipe
def getPrice(self):
return self.price
def make(self):
print(self.recipe)
class Selector(object):
def __init__(self):
self.cashBox = CashBox
self.products = []
#self.products.append(Product.
def select(self, choiceIndex):
pass
def main():
m = CoffeeMachine()
while m.oneAction():
pass
#total = m.totalCash()
#print(f"Total Cash: ${total/100:.2f}")
if __name__ == "__main__":
main()
Exception has occurred: AttributeError
'CoffeeMachine' object has no attribute 'credit'
File "C:\Users\Tanner Harmer\Desktop\Coffee2\CashBox.py", line 7, in deposit
self.credit = amount + self.credit
File "C:\Users\Tanner Harmer\Desktop\Coffee2\CashBox.py", line 46, in oneAction
CashBox.deposit(self,int(words[1]))
File "C:\Users\Tanner Harmer\Desktop\Coffee2\CashBox.py", line 89, in main
while m.oneAction():
File "C:\Users\Tanner Harmer\Desktop\Coffee2\CashBox.py", line 95, in <module>
main()
You're calling the CashBox by using the class name, like if the method were static, but you created an instance of this class (in the constructor self.cashBox = CashBox()) so use it
CashBox.deposit(self,int(words[1])) // OLD, NO
self.cashBox.deposit(self,int(words[1])) // YES
use the cashBox of the CoffeeMachine
When using #classmethod this is passed first instead of self. Now inside the method with this decorator i need to call functions that are not defined inside this decorator but are defined in the class. How can i call the two functions get_int_input and get_non_int_input so that i can pass them to the return cls(name,pay_rate,hours) statement?
class Employee(object):
def __init__(self,name,pay_rate,hours):
self.name = name
self.pay_rate = pay_rate
self.hours = ("mon","tues","wed","thursday","friday","saturday","sunday")
def get_int_input(prompt):
while True:
pay_grade = raw_input(prompt)
try:
i = int(pay_grade)
except ValueError:
print "Int Only"
else:
return i
def get_non_int_input(prompt):
while True:
a_name = raw_input(prompt)
try:
i = int(a_name)
except ValueError:
return a_name
else:
print " Strings Only"
#classmethod
def from_input(cls):
day_count = 1
hours = ("m","tue","w","thur","f","s","sun")
while day_count <= 7:
for day in hours:
day = input(" Enter hours for day " + str(day_count) + "--- ")
day_count += 1
return cls(name,pay_rate,hours)
name = get_non_int_input("\n Enter new employee name\n")
pay_rate = get_int_input("Enter pay rate ")
employee = Employee.from_input()
print str(employee)
You would add the #staticmethod decorator before the other two classes. Since they don't take either the Employee class or one of its instances as their first argument, they operate independently of a particular class or instance, and in this sense are "static".
A method decorated in this manner is an attribute of its containing class, and is called as a class attribute, for example:
>>> class Foo(object):
... #staticmethod
... def bar():
... print 'called the static method'
...
>>> Foo.bar()
called the static method
This works the same way if you're calling Foo.bar() from inside one of Foo's class methods.
There are some other problems here, though - I would advise you to seek more comprehensive review and advice.
You defined get_int_input and get_non_int_input inside the Employee class, which means that (by default) they should take an instance of Employee as the first argument. Your code is breaking that rule, which is probably the cause of problems.
Use #staticmethod decorator to indicate that get_int_input and get_non_int_input should not take an instance of Employee as the first argument.
you seem to be missing some core concept of programming
you should probably look up namespaces and scope in google.
you should probably not talk down to john.r.sharp as he is very helpful and I would hazard a guess that if you continue programming you will have many many more problems that you come to SO for help with
all that said here is your fixed code
#first pull these two functions out of your class they have nothing to do with employee
#they should just be normal functions #
#... if you wanted to make them part of a class make an input class and add them as static methods to that
def get_int_input(prompt):
while True:
pay_grade = raw_input(prompt)
try:
i = int(pay_grade)
except ValueError:
print "Int Only"
else:
return i
def get_non_int_input(prompt):
while True:
a_name = raw_input(prompt)
try:
i = int(a_name)
except ValueError:
return a_name
else:
print " Strings Only"
class Employee(object):
def __init__(self,name,pay_rate,hours):
self.name = name
self.pay_rate = pay_rate
self.hours = ("mon","tues","wed","thursday","friday","saturday","sunday")
#classmethod
def from_input(cls):
day_count = 1
hours = ("m","tue","w","thur","f","s","sun")
while day_count <= 7:
for day in hours:
day = input(" Enter hours for day " + str(day_count) + "--- ")
day_count += 1
#name and pay_rate must be defined prior to using them in your return function ...
name = get_non_int_input("\n Enter new employee name\n")
pay_rate = get_int_input("Enter pay rate ")
#now that you have all the info just return it
return cls(name,pay_rate,hours)
employee = Employee.from_input()
print str(employee)
I am just starting to learn python and am getting confused about how to pass an instance of an object as an argument for a function, below is a little bit of code I made for practice and the basic idea is that there is one garage, this garage contains no cars, and you can add cars to the garage and view their details.
class Garage:
cars = []
def add_car(self, car):
cars.append(car)
class Car:
car_name, car_price, car_colour, car_miles, car_owners = "", "", "", "", ""
def add_new_car(self, garage, name, price, colour, miles, owners):
car_name = name
car_price = price
car_colour = colour
car_miles = miles
car_owners = owners
garage.add_car(self)
def main(argv=None):
your_garage = Garage()
while True:
print "Your garage contains %d cars!" % len(your_garage.cars)
print "1) Add a new car\n2) View your car's\n0) Leave the garage"
user_input = raw_input("Please pick an option: ")
if user_input == "1":
add_car(your_garage)
elif user_input == "2":
view_cars(your_garage)
elif user_input == "0":
quit()
def add_car(garage):
name = raw_input("Name: ")
price = raw_input("Price: ")
colour = raw_input("Colour: ")
miles = raw_input("Miles: ")
owners = raw_input("Owners: ")
car = Car()
car.add_new_car(garage, name, price, colour, miles, owners)
def view_cars(garage):
for x in xrange(len(garage.cars)):
print garage.cars[x].car_name
print garage.cars[x].car_price
print garage.cars[x].car_colour
print garage.cars[x].car_miles
print garage.cars[x].car_owners
if __name__ == "__main__":
main()
My code might be very wrong or there might be an easy way to do this, I the way I pictured it was going to be that the new instance of car I created would be passed into the add_car() function in Garage so that it can be added to the list of cars. How can I do this?
Maybe this simplified example will point you in the right direction. One of the main problems in your current code is that you should be setting instance-level attributes (for example, a car's color or a garage's inventory of cars) inside the __init__ method (or in some other method operating on instances), not up at the class level.
class Garage:
def __init__(self):
self.cars = [] # Initialize instance attribute here.
def add_car(self, car):
self.cars.append(car)
class Car:
def __init__(self, color):
self.color = color # Ditto.
def __repr__(self):
return "Car(color={})".format(self.color)
def main():
g = Garage()
for c in 'red green blue'.split():
c = Car(c)
g.add_car(c) # Pass the car to the garage's add_car method.
print g.cars # [Car(color=red), Car(color=green), Car(color=blue)]
if __name__ == "__main__":
main()
Create a CashRegister class that can be used with the RetailItem class. The CashRegister class should be able to internally keep a list of RetailItem objects. The class should have the following methods:
• A method named purchase_item method that accepts a RetailItem object as an argument. Each time the purchase_item method is called, the RetailItem object that is passed as an argement should be added to the list.
• A method name get_total that returns the total price of all the RetailItem objects stored in the CashRegister object’s internal list.
• A method name show_items that displays data about the RetailItem objects stored in the CashRegister object’s internal list.
• A method named clear that should clear the CashRegister object’s internal list.
Demonstrate the CashRegister class in a program that allows the user to select several items for purchase. When the user is ready to check out, the program should display a list of all the items he or she has selected for purchase, as well as the total price.
class RetailItem:
# The __init__ method initializes the attributes.
def __init__(self, item, units, price):
self.__item = item
self.__units = units
self.__price = price
# The following methods are mutators for the class.
def set_item(self, item):
self.__item = item
def set_units(self, units):
self.__units = units
def set_price(self, price):
self.__price = price
# The following methods are accessors for the class.
def get_item(self):
return self.__item
def get_units(self):
return self.__units
def get_price(self):
return self.__price
# The __str__ method returns the object's state as a
# string.
def __str__(self):
return 'Item Description:' + self.__item, \
'\tNumber of Units:' + self.__units, \
'\tPrice: $' + self.__price
# The decrementInventory function decreases the number
# units each time called.
def decrementInventory(units):
if units > 0:
units -= 1
else:
units = 0
# EOF
I believe this RetailItem class is correct and there is no need
class CashRegister:
# The __init__ method initializes the attributes.
def __init__(self, purchase_item):
self.__purchase_item = []
def purchase_item(item, units):
purchase_item.append(item)
decrementInventory(units)
def get_total(price):
total += price
return total
def show_items(item_list):
for item in item_list:
print(item.get_item())
print(item.get_units())
print(item.get_price())
print()
def clear():
purchase_list [:] = []
# EOF
I am not sure if I have this coded properly for the requirements.
Req. A CashRegister object has one attribute, which initialized as an empty list and write the other four methods as previously mentioned.
For the program:
The main method, create 3 retail objects, then initialize a CashRegister object for the user. Write a method to display information on the retail items created, (call str method).
The following code is what I started with and I am having problems with the four methods from the CashRegister class.
import retail_item
import cash_register
SHOW = 1
PURCHASE = 2
CART = 3
TOTAL = 4
EMPTY = 5
QUIT = 6
def main():
mylist = make_list()
mycashregister = cash_register.CashRegister(mylist)
choice = 0
# Process menu selections until user quits program.
while choice != QUIT:
# Get the user's menu choice.
choice = get_menu_choice()
# Proces the choice.
if choice == SHOW:
__str__(item)
elif choice == PURCHASE:
purchase()
elif choice == CART:
cart(mycashregister)
elif choice == TOTAL:
total(mycashregister)
elif choice == EMPTY:
empty(mycashregister)
def make_list():
item_list = []
item = 'Jacket'
units = 12
price = 59.95
entry = retail_item.RetailItem(item, units, price)
item_list.append(entry)
item = 'Jeans'
units = 40
price = 34.95
entry = retail_item.RetailItem(item, units, price)
item_list.append(entry)
item = 'Shirt'
units = 20
price = 24.95
entry = retail_item.RetailItem(item, units, price)
item_list.append(entry)
return item_list
# The get_menu_choice function displays the menu and gets
# a validated choice from the user.
def get_menu_choice():
print()
print('CASH REGISTER MENU')
print('-------------------------')
print('1. Show Retial Items')
print('2. Purchase an Item(s)')
print('3. Show Current Shopping Cart')
print('4. Show Total of Items Purchased')
print('5. Empty Your Shopping Cart')
print('6. Quit the program')
print()
# Get the user's choice.
choice = int(input('Enter your choice: '))
# Validate the choice.
while choice < SHOW or choice > QUIT:
choice = int(input('Enter a valid choice: '))
# Return the user's choice.
return choice
def display_list(item_list):
for item in item_list:
print('Item Description:', item.get_item(), \
'\tNumber of Units:', item.get_units(), \
'\tPrice:', item.get_price())
print()
def purchase():
item_purchase = input('Enter the item you wish to purchase: ')
main()
#not EOF more to come if I can figure out the first parts.
Any help would be appreciated.