Using variables to create class objects - python

This is my first question on here, so I hope I am asking the 'right' way. The code below is supposed to generate a class object, which should be named via the function createAccount() at the end. I was expecting the account to be a combination of surname and dob, however it creates the class object called accountName and not the product of the variable itself. I can see why it is doing this, but i cannot see how to correct it.
class Account(object):
def __init__(self, balance):
self.balance = balance
def deposit(self,amount):
self.balance += amount
print(self.balance)
return self.balance
def withdraw(self,amount):
if amount <= self.balance:
self.balance -= amount
print(self.balance)
return self.balance
else:
print("You do not have sufficient funds for this transaction, please contact your local branch manager")
def printBalance(self):
print(self.balance)
def createAccount():
name = input("Client Surname")
dob = input("client Date of Birth")
accountName = name+dob
print(accountName) # for debug
accountName = Account(0) # opening account balance is £0
return accountName

I think what you want is something like a "name" field in your Account object. For example:
class Account(object):
def __init__(self, name, balance):
self.name = name
self.balance = balance
. . .
def createAccount():
name = input("Client Surname")
dob = input("client Date of Birth")
accountName = name + dob
print(accountName) # for debug
account = Account(accountName, 0.0) # opening account balance is £0
return account
The object returned by createAccount contains both the account balance and the name on the account.

You are creating a variable accountName and assigning to it a text string object whose contents is the name and date of birth.
Next you're clobbering that and reassigning accountName with a new Account object you're creating. The old value for accountName gets lost when you assign something new to it.
What you need to do is pass name+dob to Account's init function, and in that function, assign the passed account name to an object variable such as self.accountName:
def __init__(self, name, balance):
self.accountName = name
self.balance = balance
...
def createAccount():
name = input("Client Surname")
dob = input("client Date of Birth")
account = Account(name+dob, 0) # opening account balance is £0
return account
Note that it's a bad idea to use name+dob as the account name, because later it'll be hard to figure out where the name ends and the date of birth begins. But at least, this will get you started.

Related

Updating the method references on VS code

I am having a hard time figuring out how to update selected references of a method from vscode. Right-clicking on the method name doesn't give the options to choose and update the references. New to Python and vscode and trying to figure out the nuances around it. Can some help me with this please!
Here are the classes - I have a class Player_Account
class Player_Account:
def __init__(self,owner,balance):
self.owner = owner
self.balance = balance
def deposit(self,balance):
self.balance += balance
return "Amount added to players pot !"
def withdraw(self,amount): # I need to update this method name to withdraw_amount
if self.balance<amount:
return "Funds Unavailable"
else:
self.balance -= amount
return "Money added to hand !"
def __str__(self):
return f"Account owner : {self.owner} has outstanding balance of {self.balance}"
Another class Player
class Player:
def __init__(self,name):
self.name=name
self.hand = []
self.player_account:Player_Account = Player_Account(name,0)
def initial_money(self,amount):
self.player_account.balance = amount
def player_won_the_hand(self,amount):
self.player_account.deposit(amount)
return True
def player_betting_amount_for_the_round(self,amount):
value = self.player_account.withdraw(amount) # I need this reference to be automatically updated as well
if value == 'Funds Unavailable':
return False
else:
return True
I just tried.
set cursor on def withdraw
press F2 (rename symbol)
change name to withdraw_amount and press Enter
it takes a few seconds but both are changed
I use PyLance.

How to store attributes of class instance in empty dictionary in Python?

I am making a custom class that performs basic banking functions.
class Account():
'''
A class to perform some basic banking functions
'''
UserList = {} #Empty dictionary to store (UID: name) for each new instance
def __init__(self, name, balance=0.0, uid=None):
self.name = name #The name of the account holder
self.balance = balance #The initial balance
self.uid = uid #User ID number chosen by account holder
#classmethod
def new_account(cls):
'''
New user can specify details of account through this class method via input()
'''
return cls(
input('Name: '),
int(input('Balance: ')),
int(input('UID: ')),
)
def withdraw(self, amount):
if amount > self.balance:
raise RuntimeError('Amount greater than available balance.')
else:
self.balance -= amount
return print("After a withdrawl of {}, {}'s current balance is {}".format(amount, self.name, self.balance)) #printing balance after withdrawl
def deposit(self, amount):
self.balance += amount
return print("After a deposit of {}, {}'s curent balance is {}".format(amount, self.name, self.balance)) # printing balance after deposit
Basically, a new user is created by creating an instance of the Account() class and it accepts a name, initial balance, and a user ID. I added a class method to take this data in through user input when Account.new_account() is called. What I am now looking to do is store the User ID and name for each instance(account) in an empty dictionary. I have been playing around with this for a few hours, and what I was thinking was something like this
def add_user(self, uid, name):
UserList[int(self.uid)] = self.name
inserted somewhere but I tried implementing this in a few places in my code and it continued to just return an empty dictionary. Could someone help point me in the right direction. Also, the two other things I am trying to implement along with this is a way to prevent users from selecting the same UID and a way to require the UID to be exactly 5 numbers. I am relatively new to Python. Thank you.
You can define a dict as a class variable as you already did, but add the UID as a key to the dict in the __init__ method instead of a separate add_user method so that you can always validate the UID when an object is instantiated, no matter how:
class Account():
users = {}
def __init__(self, name, balance=0.0, uid=None):
if uid in self.users:
raise ValueError("UID '%s' already belongs to %s." % (uid, self.users[uid].name))
if len(uid) != 5 or not uid.isdigit():
raise ValueError("UID must be a 5-digit number.")
self.name = name
self.balance = balance
self.uid = uid
self.users[uid] = self
First noticed that you cant to a "return print(...", remove print.
You can do something like this
class Account():
'''
A class to perform some basic banking functions
'''
UserList = {} #Empty dictionary to store (UID: name) for each new instance
def __init__(self, name, balance=0.0, uid=None):
self.name = name #The name of the account holder
self.balance = balance #The initial balance
self.uid = uid #User ID number chosen by account holder
self.add_user(uid, name)
#classmethod
def new_account(cls):
'''
New user can specify details of account through this class method via input()
'''
return cls(
input('Name: '),
int(input('Balance: ')),
int(input('UID: ')),
)
def withdraw(self, amount):
if amount > self.balance:
raise RuntimeError('Amount greater than available balance.')
else:
self.balance -= amount
return "After a withdrawl of {}, {}'s current balance is {}".format(amount, self.name, self.balance) #printing balance after withdrawl
def deposit(self, amount):
self.balance += amount
return "After a deposit of {}, {}'s curent balance is {}".format(amount, self.name, self.balance) # printing balance after deposit
def add_user(self, uid, name):
self.UserList[int(uid)] = name
a = Account("new user", 100, 1)
a.add_user(2, "new user")
a.add_user(3, "new user")
print(a.UserList)
this will output {1: 'new user', 2: 'new user', 3: 'new user'}
Reference the static variable from the class name:
class Account():
user_list = {}
def __init__(self, uid):
self.uid = uid
Account.user_list[uid] = self
a = Account('uid')
print(a.user_list)
# {'uid': <__main__.Account object at 0x1043e7b38>}
For what it's worth, I think a better approach would be to use 2 classes (for convenience, I'm also using dataclasses to auto-generate some functionality - it doesn't affect the core logic). Then you don't have to worry about static variables at all.
import dataclasses
from typing import Dict
#dataclasses.dataclass
class Account:
uid: str
#dataclasses.dataclass
class Bank:
accounts : Dict[str, Account] = dataclasses.field(default_factory=dict)
def add_account(self, account):
if account.uid in self.accounts:
raise ValueError(f'UID : {account.uid} already exists!')
self.accounts[account.uid] = account
b = Bank()
a1 = Account('a1')
b.add_account(a1)
print(b)
# Bank(accounts={'a1': Account(uid='a1')})

Is it possible to access instance attributes separately in a class in python?

In the below code if I create an instance of account as accnt and write accnt.owner, the program returns the memory location and not the value at the location. If i use str() method for the owner and balance I am able to obtain accnt.owner and accnt.balance values simultaneously.Is it possible to access both of them separately by just typing
accnt.owner) \n
accnt.balance
without using print function?
class Account():
def __init__(self,owner,balance):
self.owner = owner
self.balance = balance
accnt = ("Jose",100)
acct.owner----> Should output Jose
acct.balance---->Should output 100
You are making a mistake, you have to indicate what class you are trying to instantiate:
class Account():
def __init__(self, owner, balance):
self.owner = owner
self.balance = balance
accnt = ("Jose", 100) # <------------- This is wrong
accnt = Account("Jose",100) # <------- This is right
print(acct.owner)
print(acct.balance)
When you call a variable from the console, it gets printed, but from a code script, you must use print().

Return Dictionary in using str in python

I have a bank account OOP project I am working on. And I can't seem to figure out this one bug. In brief, I would like to return a users bank account after they have added it. I have included all the code because I've solved this in an object-oriented way. The str() method seems to be the problem.
from enum import Enum
class AccountType(Enum):
SAVINGS = 1
CHECKING = 2
class BankAccount():
def __init__(self, owner, accountType):
self.owner = owner
self.accountType = AccountType(accountType)
self.balance = 0
def withdraw(self, amount):
if amount > self.balance:
raise Exception('Your balance is' + self.balance + 'cannot take this much money!')
else:
self.balance -= amount
def deposit(self,amount):
self.balance += amount
def __str__(self):
return "Owner: {}. Account type is: {} ".format(self.owner, AccountType(self.accountType).name)
def __len__(self):
return self.balance
#This class is responsible for returning information about the user and their account type.
class BankUser():
#initialize an accounts dictionary.
accounts = {}
def __init__(self, owner):
self.owner = owner
def addAccount(self, accountType):
if self.accounts.get(accountType) != None:
raise Exception('Cannot have more than 1 ' + AccountType(accountType).name + ' account!')
self.accounts[accountType] = BankAccount(self.owner, accountType)
#test if user inputs an account, otherwise throw an error
def getBalance(self, accountType):
return len(self.accounts[accountType])
def deposit(self, accountType, amount):
if (accountType in self.accounts and isinstance(self.accounts[accountType], BankAccount)):
self.accounts[accountType].deposit(amount)
else:
raise Exception(self.owner + ' does not have a ' + AccountType(accountType).name + ' account!')
def withdraw(self, accountType, amount):
self.accounts[accountType].withdraw(amount)
def __str__(self):
return "Your account is {}".format(AccountType(accountType).name)
user = BankUser("David")
user.addAccount(1)
print(user)
#OUTPUT
TypeError: __str__() missing 1 required positional argument: 'accountType'
I would like to return a users account. How do I do that? Everything I have tried has ended up with this error.
You will need to move the accounts dictionary to be owned by a single bank user instance, not the bank user class (move to the __init__)
Then, all your methods have accountType except __str__, so you cannot just access it as a variable, but you could return the whole dictionary instead.
class BankUser():
def __init__(self, owner):
self.owner = owner
#initialize an accounts dictionary.
self.accounts = {}
...
def __str__(self):
return "Accounts: {}".format(self.accounts)
Or you can do [AccountType(type).name for type in self.accounts]

How do I access a class instance in a list when there is multiple classes?

I'm a beginning programmer who is building a program that simulates a bank with multiple bank accounts that a user can withdraw/deposit cash, create accounts, get exchange rates, etc. Currently, I'm trying to access a group of instances in my class that are all objects of my account class. The Account Manager class is responsible for managing these account objects and helping to organize them when user input is required. Right now, I'm trying to simulate my 3rd option on my menu which gets info on the account of a user's choice(they must manually put the ID of their account in in order to retrieve information on it, withdraw/deposit cash, etc.). Although I've managed to store all of these class instances in a list, I can't seem to use my get_account method to retrieve these for use. I'll post all of my code below. If you see anything else that is out of place, feel free to let me know.
Code:
# Virtual Bank
# 3/21/13
# Account Manager Class
class AccountManager(object):
"""Manages and handles accounts for user access"""
# Initial
def __init__(self):
self.accounts = []
# create account
def create_account(self, ID, bal = 0):
# Check for uniqueness? Possible method/exception??? <- Fix this
account = Account(ID, bal)
self.accounts.append(account)
def get_account(self, ID):
for account in self.accounts:
if account.ID == ID:
return account
else:
return "That is not a valid account. Sending you back to Menu()"
Menu()
class Account(object):
"""An interactive bank account."""
wallet = 0
# Initial
def __init__(self, ID, bal):
print("A new account has been created!")
self.id = ID
self.bal = bal
def __str__(self):
return "|Account Info| \nAccount ID: " + self.id + "\nAccount balance: $" + self.bal
# Main
AccManager = AccountManager()
def Menu():
print(
"""
0 - Leave the Virtual Bank
1 - Open a new account
2 - Get info on an account
3 - Withdraw money
4 - Deposit money
5 - Transfer money from one account to another
6 - Get exchange rates(Euro, Franc, Pounds, Yuan, Yen)
"""
) # Add more if necessary
choice = input("What would you like to do?: ")
while choice != "0":
if choice == "1":
id_choice = input("What would you like your account to be named?: ")
bal_choice = float(input("How much money would you like to deposit?(USD): "))
AccManager.create_account(ID = id_choice,bal = bal_choice)
Menu()
elif choice == "2":
acc_choice = input("What account would you like to access?(ID only, please): ")
AccManager.get_account(acc_choice)
print(acc_choice)
Menu()
Your Account objects don't actually seem to have ID attributes; instead, they have id attributes. Python is case-sensitive; try changing if account.ID == ID to if account.id == ID.
EDIT:
You are also returning after the very first mismatch. You need to remove one level of indentation from your else block so that you get through the entire loop first, and in fact, your else block shouldn't even be an else block, since you're not actually matching an if; the method should only fail if none of the accounts match the given ID.
EDIT 2:
Also, you're not actually assigning the return value from get_account() to anything, so it's lost. I'm not exactly sure what you expect to happen there.
The error lies in lines 31 and 35. You have written "id" instead of "ID". Fully capitalize those two things such that:
class Account(object):
"""An interactive bank account."""
wallet = 0
# Initial
def __init__(self, ID, bal):
print("A new account has been created!")
self.ID = ID
self.bal = bal
def __str__(self):
return "|Account Info| \nAccount ID: " + self.ID + "\nAccount balance: $" + self.bal
Please let us know if the code works after that.

Categories