Classes and Instances - python

I am new to OOP and practicing by writing a budget class as asuch:
class Budget:
category_record = []
def __init__(self, category = '', balance = 0):
self.category = category
self.balance = balance
Budget.category_record.append(self)
def deposit(self, amount):
self.balance += amount
print(f"You have deposited {amount} into your {self.category} Budget, your balance is {self.balance}")
return
def withdraw(self, amount):
if amount > self.balance:
print('Insufficient Balance, unable to withdraw')
else:
self.balance -= amount
print(f"You have withdrawn {amount} from your {self.category} Budget, your balance is {self.balance}")
return
def category_balance(self):
print(f'Your balance is {self.balance} for your {self.category} budget')
IM trying to keep a record of all instances of the budget class as a method(Forgive me if my terms are wrong, still getting used to them)
# Instantiate Food budget
food = Budget('food')
# deposit 200 into food budget
food.deposit(200)
# withdraw 100 from food budget
food.withdraw(100)
#instantaite rent budget
rent = Budget('house', 5000)
# check balance of rent budget
rent.category_balance()
Such that when I call a record method on the budget class I can get a list of ['food', 'rent']
or if possible a dictionary with the key as category and value as balance {'food':100...}

To elaborate on my #classmethod comment:
class Budget:
category_record = []
def __init__(self, category = '', balance = 0):
self.category = category
self.balance = balance
Budget.category_record.append(self)
def deposit(self, amount):
self.balance += amount
print(f"You have deposited {amount} into your {self.category} Budget, your balance is {self.balance}")
return
def withdraw(self, amount):
if amount > self.balance:
print('Insufficient Balance, unable to withdraw')
else:
self.balance -= amount
print(f"You have withdrawn {amount} from your {self.category} Budget, your balance is {self.balance}")
return
def category_balance(self):
print(f'Your balance is {self.balance} for your {self.category} budget')
#classmethod
def budget_list(cls):
if len(Budget.category_record)== 0:
print("No budgets created")
else:
print("Budget Categories:")
for budge in Budget.category_record:
print(budge.category)
#classmethod
def full_report(cls):
if len(Budget.category_record)== 0:
print("No budgets created")
else:
print("Budget Balances:")
for budge in Budget.category_record:
print(f"{budge.category} : {budge.balance}")
# Instantiate Food budget
food = Budget('food')
# deposit 200 into food budget
food.deposit(200)
# withdraw 100 from food budget
food.withdraw(100)
#instantaite rent budget
rent = Budget('house', 5000)
# check balance of rent budget
rent.category_balance()
Budget.budget_list()
Budget.full_report()

If you want to get a list of all of the instances of the Budget class, your method can just return the category_record list in which you have already been storing all instances as they are created. However, it seems you want the list to contain the names (identifiers) of the variables to which you are assigning the instances. The Budget class will have no way to access those names, so instead, I recommend you try and use the category names as that will be recorded in your category_record variable.
From your question I'm assuming you want the method to be called record. The best way to do this is to use a class method with the built-in classmethod decorator. These methods act on the class itself, and not an instance, and thus take a cls parameter instead of a self parameter (both of those names are only the convention, however I strongly advise against straying from the convention as it will make your code unnecessarily complex for everyone else). For example:
class Budget:
...
# other code
....
category_record = []
#classmethod
def record(cls):
return [budget.category for budget in cls.category_record]
# If you are unfamiliar with this syntax, search up "list comprehensions"
# Access the list
print(Budget.category_record)
If you want a dictionary instead, you can replace that method with this:
class Budget:
...
# other code
...
category_record = []
#classmethod
def record(cls):
return {budget.category:budget.balance for budget in cls.category_record}
# If you are unfamiliar with this syntax, search up "dictionary comprehensions"
# Access the dictionary
print(Budget.category_record)

Related

Call atribute of class object in class function

class client:
def __init__(self):
self.name = str(input("Name: "))
self.surname = str(input("Surname: "))
self.year = str(input("Year of birth: "))
self.id =(self.name[0] + self.surname[0] + self.year)
self.balance = 0
def Transfer(self):
balance = self.balance
action = int(input("How much would you like to transfer ?"))
if action > balance:
print("Not enough money")
else:
id = str(input("choose user you want to send money to:"))
self.balance = balance - action
#call id of crated client here to choose him as reciever of transfer
print(f"Succesfully transfered {action}$, your balance right now is {self.balance}$ have a nice day !!")
def Balance(self):
print(f"Your account balance is: {self.balance}")
Task : Send money between users
Problem : i have no idea how to call specific ID of class object that will be created

Why do I get typeerror when I use variable in class python?

I have this program to bank account with a class. It is supposed to deposit a balance into the account as you can see at a1.deposit(1000) and then update the balance on the account.
class BankAccount:
def __init__(self,first_name,last_name,number,balance):
self.first_name = first_name
self.last_name = last_name
self.number = number
self.balance = balance
def deposit(self,amount):
self.balance += amount
def withdraw(self,amount):
self.withdraw -= amount
def print_info(self):
first=self.first_name
last=self.last_name
number=self.number
balance = self.balance
s=f'{first} {last}, {number}, balance: {balance}'
print(s)
a1= BankAccount('Gang', 'Land', '19371554951', '20000')
a1.deposit(1000)
print(a1.balance)
I dont understand whats wrong because I get only type error:
self.balance += amount
TypeError: can only concatenate str (not "int") to str
I believe your error is with this line :
a1= BankAccount('Gang', 'Land', '19371554951', '20000')
if you are wanting to increase the value of the balance, then you need to initiate that variable as an integer or float. So just remove the '' around the 20000 and try again.

NameError: throwing error as name 'self' is not defined

class Account():
def __init__(self,owner,balance):
self.owner = owner
self.balance = balance
def __str__(self):
return "Account owner : {}\nAccount balance: {}".format(self.owner,self.balance)
def deposit(amount):
print ("How much you want to deposit")
amount = int(input())
self.balance = (balance) + (amount)
return "Deposit Accepted\nThe new balance is {}".format(self.balance)
def withdraw(amount):
if (self.balance >= amount):
self.balance = self.balance - amount
return "Withdrawal Accepted\nThe new balance is {}".format(self.balance)
else:
return "Insufficient funds!!"
Account_1 = Account("sammy",500)
print(Account_1)
Account_1.owner
Account_1.balance
Account_1.deposit()
Account_1.withdraw(650)
Account_1.withdraw(300)
while executing this code i am getting error as "NameError: name 'self' is not defined"
i dont understand why i a getting this error since 'self' is used as 'self reference'for a class and i've done it already.
this code is just a simple problem which i got to solve while studying classes and methods.
self should be the first argument to any method in a class that uses self (e.g. self.balance), so your withdraw and deposit methods are missing a self:
def deposit(self,amount):
print ("How much you want to deposit")
amount = int(input())
self.balance += amount
return "Deposit Accepted\nThe new balance is {}".format(self.balance)
def withdraw(self,amount):
if (self.balance >= amount):
self.balance = self.balance - amount
return "Withdrawal Accepted\nThe new balance is {}".format(self.balance)
else:
return "Insufficient funds!!"
Note that you're missing the amount in your self.deposit() statement. There's also a missing self in self.balance in your deposit method.
deposit and withdraw are member functions. So member functions should have first argument as self.
Then deposit function do not need an argument in the function definition. Here is the corrected code. Also it would be helpful if you post the stack trace for the error. That would help to zero in on the issue fast.
class Account():
def __init__(self,owner,balance):
self.owner = owner
self.balance = balance
def __str__(self):
return "Account owner : {}\nAccount balance: {}".format(self.owner,self.balance)
def deposit(self):
print ("How much you want to deposit")
amount = int(input())
self.balance = self.balance + amount
return "Deposit Accepted\nThe new balance is {}".format(self.balance)
def withdraw(self, amount):
if (self.balance >= amount):
self.balance = self.balance - amount
return "Withdrawal Accepted\nThe new balance is {}".format(self.balance)
else:
return "Insufficient funds!!"
Account_1 = Account("sammy",500)
print(Account_1)
Account_1.owner
Account_1.balance
Account_1.deposit()
Account_1.withdraw(650)
Account_1.withdraw(300)

python: pass data to class constructor

I have an Account class that has 3 data fields (id, balance, annual interest rate). Everything is working well if I just print out what the balance is or call some functions to get the monthly interest, etc...
but I need to show the results of doing a deposit and withdrawal as well and that's where I'm stuck, I'm guessing I have to do something like this
ending_balance = account.withdraw(2500) + account.deposit(3000)
but I'm not sure how to the take that ending balance and pass it to the Account constructor so that the interest rates will adjust according to the new balance.
class Account:
def __init__(self, id, balance, annual_interest_rate):
self.__id = id
self.__balance = balance
self.__annual_interest_rate = annual_interest_rate
def withdraw(self, withdrawal):
return float(self.get_balance() - withdrawal)
def deposit(self, deposit):
return float(self.get_balance() + deposit)
def main():
account = Account(1122, 20000, 4.5)
ending_balance = account.withdraw(2500) + account.deposit(3000)
if __name__ == '__main__':
main()
So your withdraw and deposit have to update the actual field, to force this use your self.set_balance or just directly self.__balance = newbalance :
def withdraw(self, withdrawal):
self.set_balance(self.get_balance() - withdrawal)
return float(self.get_balance() - withdrawal)
def deposit(self, deposit):
self.set_balance(self.get_balance() + deposit)
return float(self.get_balance() + deposit)
This is Regarding the logic in the main function.
account = Account(1122, 20000, 4.5)
ending_balance = account.withdraw(2500) + account.deposit(3000)
The above line doesn't provide the ending balance.
Do these changes,
def withdraw(self, withdrawal):
self.__balance = self.get_balance() - withdrawal
return float(self.__balance)
def deposit(self, deposit):
self.__balance = self.get_balance() - deposit
return float(self.__balance)
and calling it in the main as,
account.withdraw(2500)
ending_balance = account.deposit(3000)
would provide the right ending balance.

How to call functions from one subclass to another subclass

class Acct:
def __init__(self, deposit):
self.balance = deposit
def balance(self):
print("Your balance is $",self.balance)
def getDeposit(self, deposit):
self.balance = self.balance + deposit
print("Your new balance is $",self.balance)
def getWithdraw(self, withdraw):
self.balance = self.balance - withdraw
print("Your new balance is $",self.balance)
class ChkAcct(Acct):
def __init__(self, deposit):
super().__init__(deposit)
class SavAcct(Acct):
def __init__(self, deposit):
super().__init__(deposit)
savings_account_starting_balance = float(input("Enter a starting balance for your savings account :"))
savings_account = SavAcct(savings_account_starting_balance)
savings_account.balance()
checking_account_starting_balance = float(input("Enter a starting balance for your checking account :"))
checking_account = ChkAcct(checking_account_starting_balance)
checking_account.balance()
savings_account.getDeposit(float(input("Enter a deposit ammout for savings account :")))
checking_account.getDeposit(float(input("Enter a deposit ammout for checking account:")))
savings_account.getWithdraw(float(input("Enter a withdraw ammout from savings:")))
checking_account.getWithdraw(float(input("Enter a withdraw ammout from checking:")))
I need to make 2 classes ChkAcct and SavAcct. Each class should have a balance property. Each class should have a deposit method. Each class should have a withdraw method. Each class should also have a transfer method that calls its own withdraw method and invokes the deposit method from the other class.
I can't seem to figure out how to make the transfer methods.
There are many ways to implement this.
Here's one:
class Acct:
def __init__(self, deposit):
self.balance = deposit
# Try to avoid same names for methods and properties, unless you have a good reason for it
# Otherwise you may end up with an error like this: "TypeError: 'float' object is not callable",
# when you try to call your original balance() method
# So I renamed it to getBalance()
def getBalance(self):
print("Your balance is $",self.balance)
def getDeposit(self, deposit):
self.balance = self.balance + deposit
print("Your new balance is $",self.balance)
def getWithdraw(self, withdraw):
self.balance = self.balance - withdraw
print("Your new balance is $",self.balance)
# Transfer 'amount' from current instance to 'destination' instance
def transfer(self, amount, destination):
self.getWithdraw(amount)
destination.getDeposit(amount)
class ChkAcct(Acct):
def __init__(self, deposit):
super().__init__(deposit)
class SavAcct(Acct):
def __init__(self, deposit):
super().__init__(deposit)
# Set up the accounts and fund them
print("1. Setting accounts")
savings_account = SavAcct(100.00)
checking_account = ChkAcct(200.00)
savings_account.getBalance()
checking_account.getBalance()
# Now do the transfer
print("2. Transferring money")
savings_account.transfer(50.00, checking_account)
The output will be this:
# 1. Setting accounts
# Your balance is $ 100.0
# Your balance is $ 200.0
# 2. Transferring money
# Your new balance is $ 50.0
# Your new balance is $ 250.0
The other way is to have a standalone function for this:
def transfer(amount, origin, destination):
origin.getWithdraw(amount)
destination.getDeposit(amount)
And then call it:
transfer(50.00, savings_account, checking_account)
class Acct:
def __init__(self, deposit):
self.balance = deposit
def getBalance(self):
print("Your new "+str(self.__class__.__name__)+" balance is $",self.balance)
def getDeposit(self, deposit):
self.balance = self.balance + deposit
print("Your new "+str(self.__class__.__name__)+" balance is $",self.balance)
def getWithdraw(self, withdraw):
self.balance = self.balance - withdraw
print("Your new "+str(self.__class__.__name__)+" balance is $",self.balance)
def getTransfer (self, account, destination):
self.getWithdraw(account)
destination.getDeposit(account)
class ChkAcct(Acct):
def __init__(self, deposit):
super().__init__(deposit)
class SavAcct(Acct):
def __init__(self, deposit):
super().__init__(deposit)
savings_account_starting_balance = float(input("Enter a starting balance for your savings account :"))
new_savings_account = SavAcct(savings_account_starting_balance)
new_savings_account. getBalance()
checking_account_starting_balance = float(input("Enter a starting balance for your checking account :"))
new_checking_account = ChkAcct(checking_account_starting_balance)
new_checking_account. getBalance()
new_savings_account.getDeposit(float(input("Enter a deposit ammout for savings account :")))
new_checking_account.getDeposit(float(input("Enter a deposit ammout for checking account :")))
new_savings_account.getWithdraw(float(input("Enter a withdraw ammout from savings :")))
new_checking_account.getWithdraw(float(input("Enter a withdraw ammout from checking :")))
new_checking_account.getTransfer(float(input("Enter a transfer ammount from checking to savings :")),new_savings_account)
new_savings_account.getTransfer(float(input("Enter a transfer ammount from savings to checking :")),new_checking_account)
thanks to a friend I ended up with this. I like the added touch of calling back the class name in the output to help the user differentiate account balance

Categories

Resources