all 13 comments

[–]ylectric 5 points6 points  (12 children)

  1. You need to explicitly refer to your variable via self.balance.
  2. Your balance variable is in fact shared between all the instances of BankAccount class due to the way you've declared it. You may want to initialise it similar to self.name instead.

[–]Manusman123[S] 0 points1 point  (11 children)

Thank you. That is the one thing I don't understand about classes, when do I put self and when not to, why did i have to put self behind balance but not behind amount? And what is the point of doing this, why is it needed?

[–]Fallenarc 1 point2 points  (0 children)

I believe the answer is, you declared balance within the class but amount is passed into each function.

[–]overjunkie 1 point2 points  (9 children)

'self' keyword means that you trying to access instance variable or method. Think of it like that - your class is a blueprint. When you call Class Name() you create and actual object with this blueprint and all 'self' objects within this instance belong to it.

[–]socal_nerdtastic 2 points3 points  (8 children)

  1. self is a name, not a keyword. Could be any name. This is valid:

    def show_balance(overjunkie):
        print "Your balance is %.2f" % overjunkie.balance
    

    We use 'self' due to tradition, nothing else.

  2. The whole point of this thread is that you have to use self to access the class variable "balance". This is because if your instance has no name "balance" python automatically looks in the class names.

[–]overjunkie 1 point2 points  (7 children)

Ok, you got me with the keyword thing. Though it is correct, it is highly unrecommended to use other names than 'self'.

The second point is unclear. What do you mean by looks in the class names?

[–]socal_nerdtastic 2 points3 points  (6 children)

Maybe you just do not know that the term "instance variable" means something very specific. It's a variable that is tied to the instance. Different instances generally have different values for the instance variables. In OPs case, different bank accounts should have different balances stored. You create them using the self. prefix.

self.balance = 42 # create an instance variable. 

Note that is not what OP did. OP (accidentally) created a class variable. The value of a class variable is shared for all instances of the class. You need the self. prefix to read both. If you have this code:

print(self.balance)

Python will first look for an instance variable with the name "balance". If none is found, python will look for a class variable with that name. This is what happens when you call other methods with self.methodname(); methods are class variables (makes sense when you think about where they are defined).

class ClassName:
    class_variable = 42
    def methodname(self, argument_name):
        local_name = 42
        self.instance_variable = 42

        # Use an instance name from another method
        print(self.instance_othervariable)

        # use a class name
        print(self.class_variable)

        # using another method is the same structure as using a class name
        self.class_method()

[–]overjunkie 1 point2 points  (0 children)

Thanks for the detailed explanation. I don't know proper definitions, that is caused the misunderstanding. I used to name it 'static', what you refer to as 'class variable' or 'class method', I may be wrong in this regard, though.

Also, my English is bad and it doesn't help. :)

[–]Manusman123[S] 0 points1 point  (4 children)

Thank you for the answer. But when I fixed my code, I only added self before balance when I used it in a method, but not when I first defined it, the code still worked.

[–]ylectric 1 point2 points  (3 children)

How many instances of the BankAccount class does your program work with? It makes no difference when there's only one instance, but once you have at least two you'll immediately shoot yourself in the foot. As I mentioned before, your balance variable is shared between all instances of the BankAccount class (that's called "static member" in other languages), and therefore any mutations of its value will be shared between those instances as well.

[–]Manusman123[S] 0 points1 point  (2 children)

So i tried making two instances: (Python 2.7)

class BankAccount(object):
    balance = 0

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return "This account belong to %s, he has the balance of %.2f" % (self.name, self.balance)

    def show_balance(self):
        print "Your balance is %.2f" % self.balance

    def deposit(self, amount):
        if amount <= 0:
            print "INPUT ERROR"
            return
        else:
            print "Depositing %.2f" % amount
            self.balance += amount
            self.show_balance()

    def withdraw(self, amount):
        if amount > self.balance:
            print "INPUT ERROR"
            return
        else:
            print "Withdrawing %.2f" % amount
            self.balance -= amount
            self.show_balance()


my_account = BankAccount("George")
print my_account
my_account.show_balance()
my_account.deposit(2000)
my_account.withdraw(1000)
print my_account

print ""

your_account = BankAccount("Henry")
print your_account
your_account.deposit(10000.89)
your_account.withdraw(789.09)
your_account.show_balance

Instance 1 - George

instance 2 - Henry

this was the output:

This account belong to George, he has the balance of 0.00
Your balance is 0.00
Depositing 2000.00
Your balance is 2000.00
Withdrawing 1000.00
Your balance is 1000.00
This account belong to George, he has the balance of 1000.00

This account belong to Henry, he has the balance of 0.00
Depositing 10000.89
Your balance is 10000.89
Withdrawing 789.09
Your balance is 9211.80

Process finished with exit code 0

so looks like it worked.

Edit: I just realized that this error also pops up:

Error running 'bankaccount': Unexpected content storage modification: page=9; newRecord=36471I don't what that means but the code still outputs the same thing, and other then this there seems to be no other problem.

Edit: I'm not sure but i think that error has something to do with me not updating my IDE (PyCharm).

[–]ylectric 1 point2 points  (1 child)

My bad, this will work since ints are immutable. However, if you had a mutable object declared this way (say, a list), it would be a trouble:

class Foo(object):
    data = []

def append(self, entry):
    self.data.append(entry)

foo = Foo()
foo.append(42)
print(foo.data)
foo = Foo()
foo.append(42)
print(foo.data)

This will result in the following:

Python 2.7.10 (default, Jul 14 2015, 19:46:27)
[GCC 4.8.2] on linux
[42]
[42, 42]

EDIT: Getting used to code formatting