mjkim
mjkim

Reputation: 593

TypeError : object does not support indexing

I recently learned Python. I can't catch the error in this code. What is wrong?

class BankAccount:

    def __init__(self, initial_balance):
        """Creates an account with the given balance."""
        self  = [initial_balance, 0]

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

    def withdraw(self, amount):
        """
        Withdraws the amount from the account.  Each withdrawal resulting in a
        negative balance also deducts a penalty fee of 5 dollars from the balance.
        """
        self[0] -= amount
        if self[0] < 0:
            self[0] -= 5

        self[1] += 1

    def get_balance(self):
        """Returns the current balance in the account."""
        return self[0]

    def get_fees(self):
        """Returns the total fees ever deducted from the account."""
        return 5*self[1]


my_account = BankAccount(10)
my_account.withdraw(15)
my_account.deposit(20)
my_account.get_balance(), my_account.get_fees()

The error is:

Traceback (most recent call last):
  File "C:\Python34\bank.py", line 28, in <module>
    my_account.withdraw(15)
  File "C:\Python34\bank.py", line 15, in withdraw
    self[0] -= amount + 5
TypeError: 'BankAccount' object does not support indexing

self value contains initial_balance and a count of how many withdrawals have happened.

Upvotes: 0

Views: 13513

Answers (3)

Aswin Murugesh
Aswin Murugesh

Reputation: 11070

self always refers to the object that calls the class function. So, it is recommended not to assign something to the self variable like:

self = #something

in the constructor. Give that variable a name. Like:

self.details = [initialbalance,0]

And use the variable name wherever.

Upvotes: 3

jonrsharpe
jonrsharpe

Reputation: 122052

It should look something like this:

class BankAccount:

    OVERDRAW_PENALTY = 5

    def __init__(self, opening_balance=0):
        self.balance = opening_balance
        self.withdrawals = 0

    def withdraw(self, amount):
        self.withdrawals += 1
        self.balance -= amount
        if self.balance < 0:
            self.balance -= self.OVERDRAW_PENALTY
        return amount

Note that I am using self to access instance and class attributes, not trying to assign directly to it. Also, I have factored out the "magic number" 5, so it is clearer what is happening.

Also, your implementation of get_fees is incorrect - the number of withdrawals is currently incremented whether or not a fee is applied. You should either store a self.overdrawn_withdrawals count separately or keep a running total self.fees attribute.

Finally, I have added return amount to the end of withdraw - this allows you to do things like:

account2.deposit(account1.withdraw(100))

to easily transfer money between BankAccounts.

Upvotes: 0

mhawke
mhawke

Reputation: 87084

self refers to the BankAccount object. You need to assign and reference instance variables.

Your __init__() method should be something like this:

class BankAccount:
    def __init__(self, initial_balance):
        """Creates an account with the given balance."""
        self.balance  = initial_balance
        self.fees = 0
        self.withdrawals = 0

    def deposit(self, amount):
        """Deposits the amount into the account."""
        self.balance += amount

Similarly withdraw() and get_balance() should reference self.balance, and get_fees() should reference self.fees.

Upvotes: 0

Related Questions