I have deposit, withdraw and transfer methods in my OOP banking app that seems to be printing correct values, although if I remove the repr method it shows that 1 ID is not identical.
EDIT: My other classes, not sure if relevant here:
class PersonError(Exception):
"""Person error."""
pass
class TransactionError(Exception):
"""Transaction error."""
pass
class Person:
"""Person class."""
def __init__(self, first_name: str, last_name: str, age: int):
"""
Person constructor.
:param first_name: first name
:param last_name: last name
:param age: age, must be greater than 0
"""
if not first_name or not last_name:
raise PersonError
else:
self.first_name = first_name
self.last_name = last_name
self.bank_account = None
if age <= 0:
raise PersonError
else:
self._age = age
@property
def full_name(self) -> str:
"""Get person's full name. Combination of first and last name."""
return f"{self.first_name} {self.last_name}"
@property
def age(self) -> int:
"""Get person's age."""
return self._age
@age.setter
def age(self, value: int):
"""Set person's age. Must be greater than 0."""
if value <= 0:
raise PersonError
else:
self._age = value
def __repr__(self) -> str:
"""
Person representation.
:return: person's full name
"""
return self.full_name
class Bank:
"""Bank class."""
def __init__(self, name: str):
"""
Bank constructor.
:param name: name of the bank
"""
self.name = name
self.customers = []
self.transactions = []
def add_customer(self, person: Person) -> bool:
"""
Add customer to bank.
:param person: person object
:return: was customer successfully added
"""
if person not in self.customers:
self.customers.append(person)
person.bank_account = Account(0, person, bank)
return True
else:
return False
def remove_customer(self, person: Person) -> bool:
"""
Remove customer from bank.
:param person: person object
:return: was customer successfully removed
"""
if person in self.customers:
self.customers.remove(person)
person.bank_account = None
return True
else:
return False
def __repr__(self) -> str:
"""
Bank representation.
:return: name of the bank
"""
return self.name
class Transaction:
"""Transaction class."""
def __init__(self, amount: float, date: datetime.date, sender_account: 'Account', receiver_account: 'Account',
is_from_atm: bool):
"""
Transaction constructor.
:param amount: value
:param date: date of the transaction
:param sender_account: sender's object
:param receiver_account: receiver's object
:param is_from_atm: is transaction from atm
"""
self.is_from_atm = is_from_atm
self.receiver_account = receiver_account
self.sender_account = sender_account
self.date = date
self.amount = amount
def __repr__(self) -> str:
"""
Transaction representation.
:rtype: object's values displayed in a nice format
"""
if self.is_from_atm is True:
return f"({self.amount} €) ATM"
elif self.is_from_atm is False:
return f"({self.amount} €) {self.sender_account.person} -> {self.receiver_account.person}"
My methods:
class Account:
"""Account class."""
def __init__(self, balance: float, person: Person, bank: 'Bank'):
"""
Account constructor.
:param balance: initial account balance
:param person: person object
:param bank: bank object
"""
self.bank = bank
self.person = person
self._balance = balance
self.number = f"EE{randint(111111111111111111, 999999999999999999)}"
self.transactions = []
@property
def balance(self) -> float:
"""Get account's balance."""
return self._balance
def deposit(self, amount: float, is_from_atm: bool = True):
"""Deposit money to account."""
if amount <= 0:
raise TransactionError
elif is_from_atm is True:
t = Transaction(amount, date=datetime.date.today(), sender_account=self, receiver_account=self, is_from_atm=True)
self._balance = self._balance + amount
self.transactions.append(t)
bank.transactions.append(t)
elif is_from_atm is False:
self._balance = self._balance + amount
def withdraw(self, amount: float, is_from_atm: bool = True):
"""Withdraw money from account."""
if amount <= 0 or amount > self._balance:
raise TransactionError
elif is_from_atm is True:
t = Transaction(-amount, date=datetime.date.today(), sender_account=self, receiver_account=self, is_from_atm=True)
self._balance = self._balance - amount
self.transactions.append(t)
bank.transactions.append(t)
elif is_from_atm is False:
self._balance = self._balance - amount
def transfer(self, amount: float, receiver_account: 'Account'):
"""Transfer money from one account to another."""
fee = 5
if receiver_account == self:
raise TransactionError
elif (self._balance - fee - amount) < 0:
raise TransactionError
elif receiver_account.bank != self.bank and amount >= 0:
t = Transaction(amount, datetime.date.today(), sender_account=self, receiver_account=receiver_account,
is_from_atm=False)
self._balance = self._balance - amount - fee
self.transactions.append(t)
self.bank.transactions.append(t)
t = Transaction(amount, datetime.date.today(), sender_account=self, receiver_account=receiver_account,
is_from_atm=False)
receiver_account._balance = receiver_account._balance + amount
receiver_account.transactions.append(t)
receiver_account.bank.transactions.append(t)
elif receiver_account.bank == self.bank and amount >= 0:
t = Transaction(amount, datetime.date.today(), sender_account=self, receiver_account=receiver_account,
is_from_atm=False)
self._balance = self._balance - amount
self.transactions.append(t)
self.bank.transactions.append(t)
t = Transaction(amount, datetime.date.today(), sender_account=self, receiver_account=receiver_account,
is_from_atm=False)
receiver_account._balance = receiver_account._balance + amount
receiver_account.transactions.append(t)
If name is main :
if __name__ == '__main__':
person = Person("Ago", "Luberg", 100)
bank = Bank("TalBank")
bank.add_customer(person)
a1 = person.bank_account
person2 = Person("Mati", "Maal", 90)
bank.add_customer(person2)
a2 = person2.bank_account
a1.deposit(100)
a2.deposit(100)
a1.withdraw(10)
a2.withdraw(50)
a1.transfer(10, a2)
print(a1.transactions) # [(100 €) ATM, (-10 €) ATM, (10 €) Ago Luberg -> Mati Maal]
print(a2.transactions) # [(100 €) ATM, (-50 €) ATM, (10 €) Ago Luberg -> Mati Maal]
print(bank.transactions)
# [(100 €) ATM, (100 €) ATM, (-10 €) ATM, (-50 €) ATM, (10 €) Ago Luberg -> Mati Maal]
My output without repr when printing transactions:
1. person1 transactions [<__main__.Transaction object at 0x0000024AE1ACF4F0>, <__main__.Transaction object at 0x0000024AE1ACF490>, <__main__.Transaction object at 0x0000024AE1ACF340>]
2. person2 transactions [<__main__.Transaction object at 0x0000024AE1ACF520>, <__main__.Transaction object at 0x0000024AE1ACF400>, <__main__.Transaction object at 0x0000024AE1ACF2B0>]
3. bank transactions(person1 + person2 transactions) [<__main__.Transaction object at 0x0000024AE1ACF4F0>, <__main__.Transaction object at 0x0000024AE1ACF520>, <__main__.Transaction object at 0x0000024AE1ACF490>, <__main__.Transaction object at 0x0000024AE1ACF400>, <__main__.Transaction object at 0x0000024AE1ACF340>]
Expected output without repr method:
1. person1 transactions [<__main__.Transaction object at 0x0000024AE1ACF4F0>, <__main__.Transaction object at 0x0000024AE1ACF490>, <__main__.Transaction object at 0x0000024AE1ACF340>]
2. person2 transactions [<__main__.Transaction object at 0x0000024AE1ACF520>, <__main__.Transaction object at 0x0000024AE1ACF400>, <__main__.Transaction object at 0x0000024AE1ACF340>]
3. bank transactions(person1 + person2 transactions) [<__main__.Transaction object at 0x0000024AE1ACF4F0>, <__main__.Transaction object at 0x0000024AE1ACF520>, <__main__.Transaction object at 0x0000024AE1ACF490>, <__main__.Transaction object at 0x0000024AE1ACF400>, <__main__.Transaction object at 0x0000024AE1ACF340>]
My question is why is the last transaction object in person2 transactions not identical to the last transaction in person1 and bank transactions although with repr method they are identical.
Output with repr method :
[(100 €) ATM, (-10 €) ATM, (10 €) Ago Luberg -> Mati Maal]
[(100 €) ATM, (-50 €) ATM, (10 €) Ago Luberg -> Mati Maal]
[(100 €) ATM, (100 €) ATM, (-10 €) ATM, (-50 €) ATM, (10 €) Ago Luberg -> Mati Maal]
Thanks in advance to whomever wishes to contribute with their help! Crimson.
__repr__methods outputs an arbitrary string. It has no bearing on object identity.