[Tutor] OOPs?

Kirby Urner urnerk@qwest.net
Sat, 30 Mar 2002 16:34:01 -0800


>
>#!/usr/bin/python
>
>import time, shelve
>
>class Stock:
>         "Simple stock class, keeps history using current time"
>
>         # the constructor defines some attributes of the instance
>         def __init__(self, code, price, datetime):
>                 self.code = code
>
>                 # the history is a dictionary that tracks the instance's

Actually, history is just a simple list [], containing
(price, datetime) tuples () -- not a dictionary {}.

>                 # prices and the datetimes of those prices
>                 self.history = [(price, datetime)]
>                 self.price = price
>
>         # the newprice() method adds a new price/datetime to the
>         # instance's history dictionary

history *list* -- I won't keep saying it, now that you've
got it.

>         def newprice(self, price, datetime):
>                 self.history.append((price, datetime))
>
>         # the showhist() method prints the history of the instance
>         # (a dictionary)
>         def showhist(self):
>                 return self.history
>
>def getcode():
>         "Handle cases where user inputs code we don't have"
>
>         # accept a stock code
>         code = raw_input("Code? > ")
>
>         # check to see if stock code is in the dictionary
>         try:
>                 stockobj = stockdict[code]
>         # if it can't be done, print an error message and exit
>         except:
>                 print "Not a legal code"
>                 return 0

Another way of doing this is stockobj = stockdict.get(code,0)
-- would have to rewrite the calling function a tiny bit.
This latter syntax becomes an option only in version 2,
where I substituted a real dictionary for the shelve file
pseudo-dictionary.

>         # if it is, return the object represented by the 'stockdict[code]'
>         # element of the dictionary that keeps track of stock objects by code
>         return stockobj
>
>def addstock():
>         "Add new stock, any code acceptable"
>
>         # accept a stock code
>         code = raw_input("Code? > ")
>         # accept a price
>         price = raw_input("Price? > ")
>         # assign an instance of the Stock class to 'stockdict[code]'
>         stockdict[code] = Stock(code, price, time, asctime())

More error check could go here, if you wanted to guard
the price from being assigned some nonsense.

>def update():
>         # assign to 'obj' an instance of the Stock class from getcode()
>         obj = getcode()
>
>         # if a Stock class instance was pulled and assigned to 'obj'
>         if obj:

Actually, not that I look at it,

    stockobj = stockdict.get(code,0)

in getcode (without a try block) wouldn't require any
rewrite.  In other words, getcode could be:

def getcode():
     "Handle cases where user inputs code we don't have"
     code = raw_input("Code? > ")
     stockobj = stockdict.get(code,0)
     return stockobj

>                 # accept a price
>                 price = raw_input("Price? > ")
>                 # call the newprice() method of the instance
>                 obj.newprice(price, time.asctime())
>                 # print the number of items in the instance's history 
> dictionary
>                 print "%s prices on file" % len(obj.history)
>                 # would not have to do next step if using real dictionary
>                 stockdict[obj.code] = obj       # overwrites old copy

OK, so you're using the older version.  In the revamp, stockdict
becomes a real dictionary {}, with the shelve construct
only being used at the start and end of mainloop, to read
from and write to disk.

>def dumphist():
>         # assign to 'obj' an instance of the Stock class from getcode()
>         obj = getcode()
>         # if a Stock class instance was pulled and assigned to 'obj'
>         if obj:
>                 # call the 'showhist()' method of the Stock instance 'obj',
>                 # and assign it to the 'hist' variable
>                 hist = obj.showhist()
>                 # print the value of the 'hist' variable
>                 print hist

I also made this prettier.  Here's the up to date
version of this tutorial code:

http://www.inetarena.com/~pdx4d/ocn/python/stocks.py

>def quit():
>         # call the close() method of the stockdict object
>         stockdict.close()
>         print "Stocks saved"
>
>def mainmenu():
>         "Using dictionary-like syntax to do file i/o"
>
>         # globalize the stockdict name
>         global stockdict
>         # create a 'stockdict' object and give it the current value
>         # of 'shelve.open("mystocks")'
>         stockdict = shelve.open("mystocks")
>         # create a tuple called 'callables'
>         callables = [quit, addstock, update, dumphist]
>         # display the menu

No, wait, you *are* using the more recent.  OK, well then
update() could be simpler -- check link.  I see I failed to
simplify it in my post to this list.

>         while 1:
>                 print \
>                 """
>                 (1) add new stock
>                 (2) update price of stock
>                 (3) dump history of stock
>                 (0) save/quit
>                 """
>
>                 # accept a selection
>                 sel = raw_input("Your choice: > ")
>                 try:
>                         # make sel an integer
>                         sel = int(sel)

Note that this will fail if the user type in 'a' or something
that can't convert to int.

>                         # test that sel is less than or equal to 3
>                         # and greater than or equal to 0

But if it passes this first test then....

>                         assert int(sel) <= 3 and int(sel) >= 0
>                         # call whichever function is represented by sel
>                         callables[int(sel)]()
>                         if int(sel) == 0:
>                                 break
>                 # if the try fails
>                 except:
>                         print "Not a legal choice"

Looks like you understand quite well.

Thanks for sharing your comments.

Kirby