The problem with your original code is that print_accounts()
doesn't return anything, yet you attempt to perform operations on its (nonexistent) return value.
Here is a version of your program made using classes, and with a few corrections:
class Account:
def __init__(self, id, date, balance):
self.id = id
self.date = date
self.balance = balance
def getString(self):
return self.id + "," + self.date + "," + str(self.balance)
savings = []
def add_account(date, account, balance):
savings.append(Account(date, account, balance))
def print_accounts():
for account in savings:
print(account.getString())
while True:
date = input("Enter the date, type exit to exit program: ")
if date.lower() == "exit":
break
else:
account = input('Enter the account: ')
balance = int(input('Enter the balance: '))
add_account(date, account, balance)
print_accounts()
with open("test.txt", "w") as file:
for account in savings:
file.write(account.getString() + "\n")
Some explanation regarding the class: The Account
class has 3 fields: id
, date
, and balance
. These fields are defined in the constructor (__init__()
). The class also has a method, getString()
, which I use to get the string representation of each instance.
Over all, the following changes have been made:
- Create an Account class, which serves as the template for the object which holds the data of each account.
- Use a loop to print accounts and write them to the file.
- Turn
date
into lowercase before checking to see if it is equal to "exit". This is a minor change but a good habit to have.
- Removed
f.close()
, as it is unnecessary when using a with open()
statement.
- Created a custom string representation of each instance of
Account
, consistent with what you would otherwise get.
That last one is achieved via defining the getString
method in the account class. There is nothing special about it, it is merely what we use to get the string representation.
A better but quite more advanced way to achieve that is by overriding the __str__
and __repr__
methods of the base object. These are essentially hidden functions that every class has, but which python defines for us. The purpose of these two specific ones is to give string representations of objects. The default code for them doesn't produce anything meaningful:
<__main__.Account object at 0x0000000003D79A58>
However, by overriding them, we can use str()
on instances of Account
, and we will get a string representation in the exact format we want. The modified class will look like so:
class Account:
def __init__(self, id, date, balance):
self.id = id
self.date = date
self.balance = balance
def __repr__(self):
return self.id + "," + self.date + "," + str(self.balance)
def __str__(self):
return self.__repr__()
This also eliminates the need to loop through savings
when writing to the file:
with open("test.txt", "w") as file:
for account in savings:
file.write(account.getString() + "\n")
Turns into:
with open("test.txt", "w") as file:
file.write(str(savings))
This wouldn't have worked before, as str()
would have given us the gibberish data you saw earlier. However, now that we have overridden the methods, it works just fine.