Private class variables (Python)

From LiteratePrograms
Jump to: navigation, search

Python does not have the concept of private class variables, offering only name-mangling to discourage internal methods from being called from outside the class.

However, Python does have lexical scoping, and with some clever trick one can get the benefits of private class variables.

In the code example below, we use the common example of a bank account class. The operations that are accessible to the public is get_balance, deposit and withdraw; the latter would fail if there are insufficient funds.

<<bank_account.py>>=

class account(object):
    def __init__(self, amount):
private_vars

private_methods

class_methods

instance_methods

        return
<<private_vars>>=
        privates = { 'balance' : amount }

The private variables need to be contained within a mutable object, otherwise attempts to modify it from a method would result in the creation of a local variable with the same name.

I use a dictionary here, but you can use a list as well. The advantage of using a dictionary is that it is more readable when you have many private variables.

<<private_methods>>=
        '''
        set_balance is a private method
        it is only visible from other methods declared
        in the constructor
        '''
        def set_balance(new_balance):
            privates['balance'] = new_balance
            return

set_balance should be kept private, since it can set the bank balance to an arbitrary amount. By defining it inside the constructor and not attaching it to either the class or the method, we ensure that it can only be called by other methods we also define inside the constructor.

<<instance_methods>>=
        '''
        get_balance is attached to the
        instance of the class, so it does not need
        to take the object self, since it is in the
        lexical scope
        '''

        def get_balance():
            return privates['balance']
        self.get_balance = get_balance

        def deposit(amount):
            bal = set_balance(get_balance() + amount)
            return
        self.deposit = deposit

Here are so-called instance methods. Note that they behave the same way as class methods, even though we attach them to the object instantiated from the class (self) rather than the class itself.

<<class_methods>>=
        '''
        withdraw is a more normal Python class method
        '''
        def withdraw(self, amount):
            bal = get_balance()
            if (bal >= amount):
                bal = set_balance(bal - amount)
                return True
            else:
                return False
        account.withdraw = withdraw

And class methods.

The only difference between the two is that if you try dir(account) after creating at least one object, the class methods will show up but the instance methods would not. It is probably preferable to use class methods for this reason.

Download code
hijacker
hijacker
hijacker
hijacker