Class not printing entire variable - python

I am failry new to coding so I've been trying to figure out how to get the entire output variable to print to the terminal. Right now the first 5 methods print when I print self.output with an instance of Change maker as gregs_vending_machine.
Notes: The round method is going to cause my numbers to get thrown off when I get to the pennies so my plan is to multiply change due by 100 and go from there.
Once I solve the way above I will refactor to solve with one method utilizing a global class dictionary for my values.
Code is Below:
class ChangeMaker:
def __init__(self, total_price, amount_paid):
self.total_price = total_price
self.amount_paid = amount_paid
self.change_due= self.change(self.total_price,self.amount_paid)
self.output = (f'For an item that costs ${self.total_price} with an amount paid of ${self.amount_paid} your change due is ${self.change_due}. Given in{self.hundreds_sentence_generator()}{self.fifties_sentence_generator()}{self.twenties_sentence_generator()}{self.tens_sentence_generator()}{self.fives_sentence_generator()}{self.dollars_sentence_generator()}\n{self.quarters_sentence_generator()}{self.dimes_sentence_generator()}{self.nickels_sentence_generator()}{self.pennies_sentence_generator()}')
self.change_output = (f'{self.quarters_sentence_generator()}{self.dimes_sentence_generator()}{self.nickels_sentence_generator()}{self.pennies_sentence_generator()}') def change(self, total_price, amount_paid):
return round(int(amount_paid) - int(total_price),2)
def hundreds_sentence_generator(self):
hundreds_due= self.change_due//round(100.00,2)
self.change_due -= round(100.00,2) * hundreds_due
if hundreds_due == 1:
return f' {int(hundreds_due)}: $100 Bill, '
elif hundreds_due > 1:
return f' {int(hundreds_due)}: $100 Bills, '
else:
return ""
def fifties_sentence_generator(self):
fifties_due= self.change_due//round(50.00,2)
self.change_due -= round(50.00,2) * fifties_due
if fifties_due == 1:
return f'{int(fifties_due)}: $50 Bill, '
elif fifties_due > 1:
return f'{int(fifties_due)}: $50 Bills, '
else:
return ""
def twenties_sentence_generator(self):
twenties_due= self.change_due//round(20.00,2)
self.change_due -= round(20.00,2) * twenties_due
if twenties_due == 1:
return f'{int(twenties_due)}: $20 Bill, '
elif twenties_due > 1:
return f'{int(twenties_due)}: $20 Bills, '
else:
return ""
def tens_sentence_generator(self):
tens_due= self.change_due//round(10.00,2)
self.change_due -= round(10.00,2) * tens_due
if tens_due == 1:
return f'{int(tens_due)}: $10 Bill, '
elif tens_due > 1:
return f'{int(tens_due)}: $10 Bills, '
else:
return ""
def fives_sentence_generator(self):
fives_due= self.change_due//round(5.00,2)
self.change_due -= round(5.00,2) * fives_due
if fives_due == 1:
return f'{int(fives_due)}: $5 Bill, '
else:
return ""
def dollars_sentence_generator(self):
dollars_due= self.change_due//round(1.00,2)
self.change_due -= round(1.00,2) * dollars_due
if dollars_due == 1:
return f'{int(dollars_due)}: $1 Bill, '
elif dollars_due > 1:
return f'{int(dollars_due)}: dollars, '
else:
return ""
def quarters_sentence_generator(self):
quarters_due= self.change_due//round(0.25,2)
self.change_due -= round(0.25,2) * quarters_due
if quarters_due == 1:
return f'{int(quarters_due)}: Quarter, '
elif quarters_due > 1:
return f'{int(quarters_due)}: Quarters, '
else:
return ""
def dimes_sentence_generator(self):
dimes_due= self.change_due//round(0.10,2)
self.change_due -= round(0.10,2) * dimes_due
if dimes_due == 1:
return f'{int(dimes_due)}: Dime, '
elif dimes_due > 1:
return f'{int(dimes_due)}: Dimes, '
else:
return ""
def nickels_sentence_generator(self):
nickels_due= self.change_due//round(0.05,4)
self.change_due -= round(0.05,2) * nickels_due
if nickels_due == 1:
return f'{int(nickels_due)}: Nickel, '
else:
return ""
def pennies_sentence_generator(self):
if self.change_due == round(0.01,2):
return f'1: Penny, '
elif self.change_due > round(0.01,2):
return f'{int(self.change_due*100)}: Pennies, '
else:
return ""
gregs_vending_machine = ChangeMaker(1.01, 190.88)
print(gregs_vending_machine.output)''

I believe your issue may be that you are casting amount_paid and total_price as integers. This will cause decimals to be truncated. If I change your change method to the following, I seem to get correct results.
def change(self, total_price, amount_paid):
return round(amount_paid - total_price, 2)

Your self.change() method is using int, so your change_due will never include any coins. So just change your self.change() to:
def change(self, total_price, amount_paid):
return amount_paid - total_price
and I think it will all work.

Related

what should have been an empty string adds a value

well I'm doing a free code camp project and something quite strange is happening to me a function works perfectly with an object instance and fails with another one creating instead of an empty string a string with a value that I had used before but I don't know what could be the cause I leave below the whole code but where you should pay attention is in line 25 which is the one that causes the error the related functions are withdraw I leave the whole code because by executing so many functions I assumed that the error could come from another so I wanted to make sure that the info is complete.
def withdraw(self, amount, cause=False):
if self.check_funds(amount):
amount = amount * -1
if cause:
self.ledger.append('"amount" : ' + str(amount) + ' "description" : ' + str(cause))
self.value += amount
print(self.ledger)
return True
else:
self.ledger.append('') # line 25
return True
whole code below
class Category:
def __init__(self, categorie):
self.categorie = categorie
self.value = 0
self.ledger = []
print ("el objeto "+ categorie + " ha sido creado")
def deposit(self, amount, cause=False):
if cause:
self.ledger.append('"amount" : ' + str(amount) + ' "description" : ' + str(cause))
self.value += amount
print(self.ledger)
else:
self.ledger.append('')
def withdraw(self, amount, cause=False):
if self.check_funds(amount):
amount = amount * -1
if cause:
self.ledger.append('"amount" : ' + str(amount) + ' "description" : ' + str(cause))
self.value += amount
print(self.ledger)
return True
else:
self.ledger.append('')
return True
else:
return False
def get_balance(self):
return self.value
def check_funds(self, amount):
if amount > self.value:
return False
else:
return True
def transfer(self, amount, category):
if self.check_funds(amount):
category.deposit(amount, "Transfer from " + self.categorie)
self.withdraw(amount, "Transfer to " + category.categorie)
return True
else:
return False
def __str__(self):
asterisk = 15 - len(self.categorie) / 2
devolver = (("*"*int(asterisk)) + self.categorie + ("*"*int(asterisk)) + "\n")
for i in self.ledger:
description = ""
amount = ""
description = i.find("description")
description = description + len("description : ")
description_str = i[description:]
for char in i:
if char in "0123456789.-":
amount += char
amount_str = amount
if len(description_str) < 23:
devolver += description_str
devolver += " "*(30-len(description_str)-len(amount_str))
devolver += amount_str+ "\n"
else:
devolver += description_str[0:23]
devolver += " "*(30-23-len(amount_str))
devolver += amount_str+ "\n"
return devolver
def create_spend_chart(categories):
pass
food = Category("Food")
food.deposit(1000, "initial deposit")
food.withdraw(10.15, "groceries")
food.withdraw(15.89, "restaurant and more food for dessert")
print(food.get_balance())
clothing = Category("Clothing")
food.transfer(50, clothing)
clothing.withdraw(25.55)
clothing.withdraw(100)
auto = Category("Auto")
auto.deposit(1000, "initial deposit")
auto.withdraw(15)
print(food)
print(clothing)
print(create_spend_chart([food, clothing, auto]))
The problem is in the __str__() method, not withdraw().
When i is an empty string, the for char in i: loop doesn't execute, so it doesn't assign amount_str. As a result, amount_str will still contain the value from the previous iteration. So any ledger entry with no cause will show with the amount from the previous iteration.
There's no need for the amount_str variable, it's the same as amount, which you correctly initialize to an empty string at the beginning of each iteration.

Why do I cannot use __repr__ data outside of a class

I started Python and struggle on using __repr__ data outside of a class. Printing the data outputs a list with lists (exactly what I wanted to do), example:
print(test) leads to:
[['Food', '-10.15', '-15.89', '-50'], ['Clothing', '-25.55'], ['Auto', '-15']]
My problem is:
print(test[0]) leads to unexpected outputs, not:
['Food', '-10.15', '-15.89', '-50']
rather than some data like:
*************Food*************
initial deposit 1000.00
groceries -10.15
restaurant and more foo -15.89
Transfer to Clothing -50.00
Total: 923.96
***********Clothing***********
Transfer from Food 50.00
-25.55
Total: 24.45
*************Food*************
initial deposit 1000.00
groceries -10.15
restaurant and more foo -15.89
Transfer to Clothing -50.00
Total: 923.96
None
.***********Business***********
deposit 900.00
-10.99
class Category:
def __init__(self, category):
self.category = category
self.balance = 0
self.ledger = []
def __repr__(self):
b = []
b.append(self.category)
for obj in self.ledger:
if str(obj['amount'])[0] == "-":
b.append(str(obj['amount']))
return str(b)
def __str__(self):
lengthTop = int((30 - len(str(self.category))) / 2)
output = "*" * lengthTop + self.category + "*" * lengthTop
for entry in self.ledger:
if len(entry['description']) > 23:
x = slice(0, 23)
output += "\n" + entry['description'][x] + ("{:7.2f}".format(entry['amount']))
else:
output += ("\n" + entry['description'] + (" " * (23 - int(len(entry['description'])))) + ("{:7.2f}".format(entry['amount'])))
output += "\n" + "Total:" + ("{:7.2f}".format(self.balance))
return output
def check_funds(self, amount):
if amount > self.balance:
return False
else:
return True
def deposit(self, amount, description=""):
self.balance += amount
self.ledger.append({"amount": amount, "description": description})
def withdraw(self, amount, description=""):
if self.check_funds(amount) == True:
self.balance -= amount
self.ledger.append({"amount": -amount, "description": description})
return True
else:
return False
def get_balance(self):
return self.balance
def transfer(self, amount, newcategory):
if self.check_funds(amount) == True:
self.withdraw(amount, "Transfer to " + newcategory.category)
newcategory.deposit(amount, "Transfer from " + self.category)
return True
else:
return False
def create_spend_chart(categories):
test = categories
print(test)

Python Class Setters Not Changing Variables

The closest thread I could find to my problem was this: Python setter does not change variable
It didn't really help, the volume and the channels are not changing at all. The first fucntion which is to "watch TV" works perfectly fine.
class TV(object):
def __init__(self, channel, volume):
self.__channel = channel
self.__volume = volume
def __str__(self):
out = ""
out += "You're on channel #" + str(self.__channel) + ", " + self.channelNetwork()
out += "\nVolume is currently at: " + str(self.__volume) + "/20"
return out
# a method that determines the name for each channel from 1-10
def channelNetwork(self):
c = self.__channel
if c == 1:
return "CBS"
elif c==2:
return "NBC"
elif c==3:
return "ABC"
elif c==4:
return "Fox"
elif c==5:
return "ESPN"
elif c==6:
return "PBS"
elif c==7:
return "CNN"
elif c==8:
return "Comedy Central"
elif c==9:
return "Cartoon Network"
elif c==10:
return "Nicklodeon"
# a volume slider that has a range from 0-20
def volumeSlider(self, newVolume):
v = self.__volume
if newVolume == "+":
v += 1
else:
v -= 1
if v < 0:
v = 0
if v > 20:
v = 20
def channelChanger(self, newChannel):
c = self.__channel
if newChannel == "+":
c += 1
else:
c -= 1
if c < 0:
c = 0
if c > 10:
c = 10
def main():
import random
randomChannel = random.randint(1,10)
randomVolume = random.randrange(21)
televsion = TV(randomChannel, randomVolume)
choice = None
while choice != "0":
print \
("""
TV Simulator
0 - Turn off TV
1 - Watch TV
2 - Change channel
3 - Change volume
""")
choice = input("Choice: ")
print()
# exit
if choice == "0":
print("Have a good day! :)")
elif choice == "1":
print("You relax on your couch and watch some TV")
print(televsion)
elif choice == "2":
newChannel = None
while newChannel not in ('+', '-'):
newChannel = input("\nPress '+' to go up a channel and press '-' to go down a channel: ")
televsion.channelChanger(newChannel)
elif choice == "3":
newVolume = None
while newVolume not in ('+', '-'):
newVolume = input("\nPress '+' to increase volume and press '-' to decrease volume: ")
televsion.volumeSlider(newVolume)
else:
print("\nSorry, but", choice, "isn't a valid choice.")
main()
input("\n\nPress enter to exit.")
The problem is, that when you do:
v = self.__volume
In:
def volumeSlider(self, newVolume):
v = self.__volume
if newVolume == "+":
v += 1
else:
v -= 1
if v < 0:
v = 0
if v > 20:
v = 20
Assigning to v won't affect self.__volume. You need to use self.__volume = 20 or whatever.
As an aside, don't use double-underscore name-mangling unless you actually need it. E.g. self.volume is fine.

Error checking inside a class

I'm supposed to create an Account class which uses some of the functions defined in the class above it. I'm having trouble with error checking in my withdraw class.
def withdraw(self, amount):
if amount > self.money:
return 'Error'
self.money -= amount
>>> a = Money(5,5)
>>> b = Money(10,1)
>>> acct1 = Account('Andrew', a)
>>> print(acct1)
Andrew's account balance is $5.05
>>> c = Money(3,50)
>>> acct1.deposit(c)
>>> print(acct1)
Andrew's account balance is $8.55
>>> acct1.withdraw(b)
>>> print(acct1)
Andrew's account balance is $-2.54
The output should be Error, but instead it just calculates and gives me back a negative balance.
The entire code is here:
class Money:
def __init__(self, dollars = 0, cents = 00):
'constructor'
self.dollars = dollars
self.cents = cents
if self.cents > 99:
self.dollars += 1
self.cents = self.cents - 100
def __repr__(self):
'standard representation'
return 'Money({}, {})'.format(self.dollars,self.cents)
def __str__(self):
'returns a string representation of ($dollars.cents)'
if self.cents < 10:
return '${}.0{}'.format(self.dollars, self.cents)
else:
return '${}.{}'.format(self.dollars, self.cents)
def __add__(self, new):
'Adds two money objects together'
d = self.dollars + new.dollars
c = self.cents + new.cents
return Money(d,c)
def __sub__(self, new):
'Subtracts two money objects'
d = self.dollars - new.dollars
c = self.cents - new.cents
return Money(d,c)
def __gt__(self, new):
'computes greater then calculations'
a = self.dollars + self.cents
b = new.dollars + new.cents
return a > b
class Account:
def __init__(self, holder, money = Money(0,0)):
'constructor'
self.holder = holder
self.money = money
def __str__(self):
return "{}'s account balance is {}".format(self.holder, self.money)
def getBalance(self):
return self.money
def deposit(self, amount):
self.money = self.money + amount
def withdraw(self, amount):
if amount > self.money:
return 'Error'
self.money -= amount
Actually it is because you don't compute the "balance" inside your __gt__ correctly.
The dollars should be multiplied by 100:
def __gt__(self, new):
a = self.dollars * 100 + self.cents
b = new.dollars * 100 + new.cents
return a > b
Optional: Instead of returning 'Error' you should consider raising an Exception:
def withdraw(self, amount):
if amount > self.money:
raise ValueError('Not enough money')
self.money -= amount

TypeError: unsupported operand type(s) for +=: 'int' and 'instancemethod'

Brand new to Python (and coding altogether). Just stepping into Object-Oriented Programming and this is the first Class I've defined, and I'm having an issue with one of the functions. The line "total += coin.value" is giving me:
TypeError: unsupported operand type(s) for +=: 'int' and 'instancemethod'
So I take it my value function is wrong, but I'm not really sure what the problem is...
import random
class Coin:
def __init__(self, coinValue=1):
if coinValue == 1:
self.coin = "Penny"
elif coinValue == 5:
self.coin = "Nickel"
elif coinValue == 10:
self.coin = "Dime"
elif coinValue == 25:
self.coin = "Quarter"
elif coinValue == 100:
self.coin = "Loonie"
else:
self.coin = "Toonie"
def __str__(self):
return self.coin
def value(self):
self.value = 0
if self == "Penny":
self.value = 1
elif self == "Nickel":
self.value = 5
elif self == "Dime":
self.value = 10
elif self == "Quarter":
self.value = 25
elif self == "Loonie":
self.value = 100
else:
self.value = 200
return self.value
def flip(self):
side = random.randint(1,2)
if side == 1:
return "Heads"
else:
return "Tails"
if __name__ == '__main__':
coin = Coin()
print 'Your first coin is a %s.' % (coin)
purse = [coin]
print 'Adding four more coins to your purse...'
for i in range(4):
coin = Coin(random.choice([1,5,10,25,100,200]))
purse.append(coin)
print 'In your purse you now have:'
for coin in purse:
print '\ta', coin
total = 0
for coin in purse:
total += coin.value
print 'The total value of the coins in your purse is', total, 'cents.'
print 'Flipping your coins you get:',
for coin in purse:
print coin.flip(),
value is the name of both a method and a field on a Coin class.
Just rename the method value to get_value and replace:
total += coin.value
with:
total += coin.get_value()

Categories