1

I have the class BankAccount that I am using to create a GUI that allows the user to make a deposit, make a withdrawal, and see their balance.

This is the BankAccount class code:

class BankAccount(object):
    """ creates a bank account with the 
        owner's name and a balance """
    def __init__(self, name, balance = 0):
        self.__name = name
        self.__balance = balance

    def getName(self):
        """ returns the owner's name """
        return self.__name

    def getBalance(self):
        """ returns the current balance """
        return round(self.__balance, 2)

    def deposit(self, amount):
        """ deposits amount into the account """
        self.__balance += amount

    def withdraw(self, amount):
        """ withdraws amount from the account
            returns 'overdrawn' if balance is too low """
        if self.__balance >= amount:
            self.__balance -= amount
        else:
            return 'overdrawn'

    def __str__(self):
        """ return a string representation of the account """
        return self.__name + ' has a balance of $' + str(round(self.__balance, 2))

And this is the GUI code:

from tkinter import *
from bankAccountClass import BankAccount




class bankAccountGUI(Frame):
    def __init__(self):
        """Set up the GUI"""
        self.__balance= 0
        Frame.__init__(self)
        self.master.title('Bank Account')
        self.grid()

        depositLabel = Label(self, text= "Make Deposit")
        depositLabel.grid(row = 0, column = 0)
        self.depositVar= DoubleVar()
        depositEntry = Entry(self, textvariable= self.depositVar)
        depositEntry.grid(row = 0, column = 1)

        withdrawLabel= Label(self, text= "Make Withdrawal")
        withdrawLabel.grid(row = 1, column = 0)
        self.withdrawVar = DoubleVar()
        withdrawEntry= Entry(self, textvariable= self.withdrawVar)
        withdrawEntry.grid(row = 1, column = 1)


        button_1= Button(self, text = "Enter", command = self.deposit)
        button_1.grid(row = 0, column = 2)

        button_2= Button(self, text = "Enter", command = self.withdrawal)
        button_2.grid(row = 1, column = 2)


    def deposit(self):
        """event handler for button_1"""
        try:
            amount= self.depositVar.get()
            balance= BankAccount.getBalance(self)
            if amount <= 0:
                messagebox.showerror(message= 'Deposit must be greater than 0')
            else:
                balance= BankAccount.deposit(self, amount)
                messagebox.showinfo(title= "Current Balance",
                                    message= "$" + self.balance,
                                    parent= self)
        except ValueError:
            messagebox.showerror(message= "Invalid deposit amount")


    def withdrawal(self):
        """event handler for button_2"""
        try:
            amount= self.withdrawVar.get()
            balance= BankAccount.getBalance(self)
            if amount > self.balance:
                messagebox.showerror(message= "Insufficient funds")
            else:
                balance= BankAccount.withdraw(self, amount)
                messagebox.showinfo(title= "Current Balance",
                                    message= "$" + self.balance,
                                    parent= self)
        except ValueError:
            messagebox.showerror(message= "Invalid withdrawal amount")

def main():
    """instantiate and pop up the window"""
    bankAccountGUI().mainloop()

I'm getting an error that I don't really know what it means or how to fix it.

Exception in Tkinter callback
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/tkinter/__init__.py", line 1442, in __call__
    return self.func(*args)
  File "/Users/tinydancer9454/Documents/python/bankAccountGUI.py", line 49, in deposit
    balance= BankAccount.getBalance(self)
  File "/Users/tinydancer9454/Documents/python/bankAccountClass.py", line 24, in getBalance
    return round(self.__balance, 2)
AttributeError: 'bankAccountGUI' object has no attribute '_BankAccount__balance'
tinydancer9454
  • 403
  • 2
  • 11
  • 20

2 Answers2

3

When you call balance= BankAccount.getBalance(self) in your deposit function, what you're actually doing is accessing the getBalance() method of the BankAccount class, using it uninitialized, and trying to pass in a different object as self. When you call a method by accessing the class instead of an instance, you do have to give it a self object for it to actually work. BankAccount methods expect their self objects to be a BankAccount object. You're passing it a BankAccountGUI object instead, which does not contain the __balance attribute. That's why its throwing that error.

What you should be doing is creating an instance of BankAccount, then using its method:

account = BankAccount()
balance = account.getBalance()

Something like that.

DaveTheScientist
  • 3,299
  • 25
  • 19
0

To understand the mention of the variable _BankAccount__balance in the error message, see the Python documentation on the use of double underscores and "name mangling":

... Since there is a valid use-case for class-private members (namely to avoid name clashes of names with names defined by subclasses), there is limited support for such a mechanism, called name mangling. Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped.

This question and its accepted answer are also informative.

The easiest way to solve this here is to just remove all the leading underscores from your class variable names. Or you could change self.__balance in the BankAccount.getBalance() function to self._BankAccount__balance.

Edit: You're also passing the bankAccountGUI object as an argument in the getBalance function, as self. It should just be balance= BankAccount.getBalance(), without self.

Community
  • 1
  • 1
Junuxx
  • 14,011
  • 5
  • 41
  • 71
  • i've fixed this and i was just wondering if you knew why a message box that simply says "alert" pops up when i hit enter for the deposit entry. I have been unable to find any information on what this means or what causes it – tinydancer9454 Apr 15 '13 at 20:15
  • Junuxx, it's not about the double underscores, its actually confusion between classes and instances of classes. The GUI object should create an instance of a BankAccount, and all of the methods in BankAccountGUI should work off of that instance, not off of the class object itself. – DaveTheScientist Apr 15 '13 at 20:24
  • @tinydancer: Just "alert" is indeed a bit unhelpful. Did you manage to find out what caused it? – Junuxx Apr 15 '13 at 21:38
  • @DaveTheScientist: You're right, although I believe name mangling was in fact unclear to OP, and my answer does partly explain the "error that [they] don't really know what it means". – Junuxx Apr 15 '13 at 21:39
  • Well that's probably true. Understanding the whole mangling of names is a very good thing to know. – DaveTheScientist Apr 15 '13 at 23:00
  • it doesnt say anything other than alert – tinydancer9454 Apr 16 '13 at 01:31