I’m working on the Budget App and running into an issue where the output from Replit does not match the output of PyCharm.
In the Category class, I store attributes for a name and a total spend.
I try to pass the value of those attributes to the external function create_spend_chart() in a loop by using iteration.attribute (i.name and i.spend). When doing this in PyCharm, everything works as I would expect it to; the values are passed into the function and it returns the expected output. However, when I implement this code in Replit, it returns the following error:
Traceback (most recent call last):
File "main.py", line 22, in <module>
print(create_spend_chart([food, clothing, auto]))
File "/home/runner/boilerplate-budget-app/budget.py", line 76, in create_spend_chart
spending.append(getattr(i,'spend'))
AttributeError: 'list' object has no attribute 'spend'. Did you mean: 'append'?
After searching for potential solutions, I tried to use getattr(), which should (to my understanding) pass the attribute to an external function successfully. It works in PyCharm, but in Replit I receive the same error as above.
I will highlight the relevant sections of code here, with the full code pasted below
class Category:
def __init__(self,name):
self.ledger = []
self.balance = float(0)
self.name = name
self.spend = float(0)
def create_spend_chart(cat1 ,cat2 = None,cat3 = None,cat4 = None) :
catdict = {}
# get the total of spending across all passed categories
spending = []
for i in [cat1, cat2, cat3, cat4]:
if i != None:
spending.append(getattr(i,'spend')) #####here (the alternative form to this that also worked in PyCharm for me was "spending.append(i.spend)"
spending = sum(spending)
# add all passed categories to a dictionary with key = category and value = percentage of total spend
for i in [cat1, cat2, cat3, cat4]:
if i != None:
PercentageSpend = getattr(i,'spend') / spending #####here#####
catdict[getattr(i,'name')] = PercentageSpend #####here#####
else:
pass
The full code is here. Again, this works outside of Replit, so I am really struggling to understand why it would be different inside of it.
class Category:
def __init__(self,name):
self.ledger = []
self.balance = float(0)
self.name = name
self.spend = float(0)
#create custom representation for print(self) 30 characters wide left/right justified item and cost
def __repr__(self):
InstPrnt = ''
#create header with name centered in asterisks
starlength = int((30 - len(self.name)) / 2)
line1 = starlength * '*' + self.name + starlength * '*'+'\n'
InstPrnt += line1
#split ledger into dictionaries
for dict in self.ledger:
WorkingDict = dict
# split dictionaries into items, and add the values (cost, and description, respectively) to a list
ledgerline = []
for i, j in WorkingDict.items():
ledgerline.append(j)
cost = str('{:.2f}'.format(ledgerline[0]))
item = ledgerline[1]
#check spacing
if (len(cost) + len(item)) > 29:
item = item[0:(29 - len(cost))]
space = 30 - (len(cost) + len(item))
#add for each dictionary in ledger to the print string
InstPrnt += (item + ' ' * space + cost + '\n')
#add the total for the entire string, formatted as a monetary value (xxxx.xx)
InstPrnt += 'Total: '+'{:.2f}'.format(self.balance)
return InstPrnt
def deposit(self,amount,description = ''):
entry = {'amount': amount, 'description': description}
self.balance += amount
self.ledger.append(entry)
def withdraw(self,amount,description = ''):
entry = {'amount': -1 * amount, 'description': description}
if self.check_funds(amount) == False :
return False
else :
self.balance += -1 * amount
self.ledger.append(entry)
self.spend += amount
return True
def transfer(self,amount,budgetcategory):
if self.check_funds(amount) == False:
return False
else:
self.withdraw(amount,'Transfer to '+str(budgetcategory.name))
budgetcategory.deposit(amount,'Transfer from '+str(self.name))
return True
def get_balance(self):
return(self.balance)
def check_funds(self,amount):
if self.balance + -1 * amount < 0 :
return False
else :
return True
#try to get it to recognize code blocks
def create_spend_chart(cat1 ,cat2 = None,cat3 = None,cat4 = None) :
catdict = {}
# get the total of spending across all passed categories
spending = []
for i in [cat1, cat2, cat3, cat4]:
if i != None:
spending.append(getattr(i,'spend'))
spending = sum(spending)
# add all passed categories to a dictionary with key = category and value = percentage of total spend
for i in [cat1, cat2, cat3, cat4]:
if i != None:
PercentageSpend = getattr(i,'spend') / spending
catdict[getattr(i,'name')] = PercentageSpend
else:
pass
#create the y axis labels
linedict = {'100|': 1.00, ' 90|': .90, ' 80|': .80, ' 70|': .70, ' 60|': .60, ' 50|': .50, ' 40|': .40, ' 30|': .30, ' 20|': .20, ' 10|': .10, ' 0|': 0}
output = ''
#create bars by testing the value from the category dictionary against the value from the line dictionary
for line in linedict:
output += line
for i in catdict:
if catdict[i] >= linedict[line]:
output += ' o '
else:
output += ' '
output += '\n'
# add the spacer bar
output += ' ' + '-' * (3 * len(catdict) + 1) + '\n'
# add the labels
# find how many extra lines to add
ExtraLines = len(max(catdict, key=len))
# print(ExtraLines)
for i in range(ExtraLines):
output += ' ' * 4
for key, value in catdict.items():
try:
x = key
output += ' ' + x[i] + ' '
except:
output += ' '
output += '\n'
return output
Your browser information:
User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/110.0
Challenge: Scientific Computing with Python Projects - Budget App
Link to the challenge: