|
First Summer 2008 |
class Account(object):
def __init__(self, initialBalance):
self.balance = initialBalance
def main():
a = Account(23)
print a.balance
a.balance = -23
print a.balance
An object can hold more than data. It can also hold methods, which encapsulate behavior.
class Account(object):
def __init__(self, initialBalance):
self.balance = initialBalance
def report(self):
print "The current balance is:", self.balance
def main():
a = Account(23)
a.report()
a.balance = -23
a.report()
For safety data should be modified through a method, not directly.
class Account(object):
def __init__(self, initialBalance):
self.balance = initialBalance
def report(self):
print "The current balance is:", self.balance
def set_balance(self, newBalance):
self.balance = newBalance
def main():
a = Account(23)
a.report()
a.set_balance(-23)
a.report()
The advantage is that you can control what goes in, and may prevent inconsistent situations (will show that soon).
Take a look at the difference between get_balance() and report().
The difference is that between return and print.
Returning a value is what allows get_balance() to make
its result available to report (the other way is impossible).
class Account(object):
def __init__(self, initialBalance):
self.set_balance(initialBalance)
def report(self):
print "The current balance is:", self.get_balance()
def set_balance(self, newBalance):
self.balance = newBalance
def get_balance(self):
return self.balance
def main():
a = Account(23)
a.report()
a.set_balance(-23)
a.report()
We can define a property now:
class Account(object):
def __init__(self, initialBalance):
self.__balance = initialBalance
def report(self):
print "The current balance is:", self.get_balance()
def set_balance(self, newBalance):
self.__balance = newBalance
def get_balance(self):
return self.__balance
balance = property(get_balance, set_balance)
def main():
a = Account(23)
a.report()
a.set_balance(-23)
a.report()
I skipped a step here, by making the balance variable private. We will see in a second what that means.
First here's the first benefit of a property, as defined:
class Account(object):
def __init__(self, initialBalance):
self.__balance = initialBalance
def report(self):
print "The current balance is:", self.get_balance()
def set_balance(self, newBalance):
if newBalance < 0:
print "Sorry, the balance is not supposed to become negative."
else:
self.__balance = newBalance
def get_balance(self):
return self.__balance
balance = property(get_balance, set_balance)
def main():
a = Account(23)
print a.balance
a.balance = -23 # complains and does not change the balance
print a.balance
So now we have both the advantage of the simpler syntax as well as that of the procedural behavior. Without the property this doesn't work at all:
class Account(object):
def __init__(self, initialBalance):
self.__balance = initialBalance
def report(self):
print "The current balance is:", self.get_balance()
def set_balance(self, newBalance):
if newBalance < 0:
print "Sorry, the balance is not supposed to become negative."
else:
self.__balance = newBalance
def get_balance(self):
return self.__balance
def main():
a = Account(23)
print a.balance
a.balance = -23
print a.balance
Objects are available from outside as hash tables but their internal state is never in jeopardy.
class Account(object):
def __init__(self, initialBalance):
self.__balance = initialBalance
def report(self):
print "The current balance is:", self.get_balance()
def set_balance(self, newBalance):
if newBalance < 0:
print "Sorry, the balance is not supposed to become negative."
else:
self.__balance = newBalance
def get_balance(self):
return self.__balance
def main():
a = Account(23)
a.__balance = -23 # does not work
print a.__balance # does not work
a.report() # prints
Names without __ are available and modifiable from outside unless they're properties. Names with __ are private and entirely accessible. Properties offer a perfect world. In exchange you need to stick with the method names.