""" Exercise 7.3 from "A primer on... The main point of the exercise is to illustrate how encapsulation works in class programming. If attributes are always accessed through methods (getters/setters) we can change the internal data structure without any consequences for users of the class. (A secondary point is to introduce the useful datetime module.) """ from datetime import datetime class AccountP: def __init__(self, name, account_number, initial_amount): self._name = name self._no = account_number self._transactions = [{'time':datetime.now(),'amount':initial_amount}] def deposit(self, amount): trans = {'time':datetime.now(),'amount':amount} self._transactions.append(trans) def withdraw(self, amount): trans = {'time':datetime.now(),'amount': -amount} self._transactions.append(trans) def get_balance(self): balance = sum([t['amount'] for t in self._transactions]) return balance def dump(self): s = f'{self._name}, {self._no}, balance: {self._balance}' print(s) def print_transactions(self): for t in self._transactions: time = t['time'].strftime('%a %d %b %Y, %H:%M:%S') amount = t['amount'] print(f'{time}: {amount}') #example usage: a1 = AccountP('John Olsson', 19371554951, 20000) a1.withdraw(4000) #print(a1._balance) # it works, but a convention is broken print(a1.get_balance()) # correct way of viewing the balance a1.print_transactions()