help with my first use of a class

Bruno Desthuilliers onurb at xiludom.gro
Fri Oct 20 11:17:30 CEST 2006


BartlebyScrivener wrote:
> I am a mere hobbyist. Spent several hours trying to make a class,
> because I think this is an occasion where I need one. But I can't make
> it work.
> 
> This code "works" (only because of the global c, which I know I'm
> supposed to avoid, by using a Class). I edited the rest to leave out
> the irrelevant formatting and printing of the quotations.
> 
> I've read about Classes several times, but I don't "get" them yet.

Think of a class as both a "blueprint" for objects and a factory
creating these objects. The class lets you define the attributes and
behaviors of it's instances.

> Obviously. If I can solve one real life problem like this, then maybe
> I'll see the light.
> 
> If I understand the power of Classes correctly, I could make one that
> would allow me to make a new instance that would connect to, say, an
> SQLite3 db instead of the Access db, as well as to create more methods
> that will do different SQL searches.


> Thank you for any help,
> 
> 
> import mx.ODBC.Windows as odbc
> import sys
> import random
> 
> def connect():
>     global c
>     db='DSN=Quotations'
>     conn = odbc.DriverConnect(db)
>     c = conn.cursor()
> 
> def random_quote():
>     """
>     Counts all of the quotes in MS Access database Quotations2005.mdb.
>     Picks one quote at random and displays it using textwrap.
>     """
>     c.execute ("SELECT COUNT(Quote) FROM PythonQuoteQuery")
>     # Yields the number of rows with something in the quote field
>     total_quotes = c.fetchone()
>     # Get a random number somewhere between 1 and the number of total
> quotes
>     quote_number = (random.randint(1, total_quotes[0]),)
>     # Select a quote where the ID matches that number
>     c.execute ("SELECT Author, Quote FROM PythonQuoteQuery WHERE ID=?",
> quote_number)
>     quote = c.fetchone()
>     blah blah blah
> 
> def print_quote()
>     code to format and print the quote (which will also have to be
> global, unless I learn Classes!)
> 

Ever wondered what arguments and return values were for ?-)

> if __name__ == '__main__':
>     if len(sys.argv) == 1:
>         connect()
>         random_quote()
>         print_quote()
> 

First, notice that you *don't* need a class here to avoid globals.
Learning to use function as *functions* (ie: taking arguments and
returning values) instead of procedure would help:

def random_quote(cursor):
  c.execute ("SELECT COUNT(Quote) FROM PythonQuoteQuery")
  total_quotes = c.fetchone()
  quote_number = (random.randint(1, total_quotes[0]),)
  c.execute (
    "SELECT Author, Quote FROM PythonQuoteQuery WHERE ID=?",
     quote_number
  )
  return c.fetchone()

def format_quote(quote):
  # code here
  return formatted_quote

def main(*args):
  if len(args) < 2:
    print >> sys.stderr, "Missing dsn arg\nusage : %s dsn" % args[0]
    return 1
  dsn = args[1]
  try:
    conn = odbc.DriverConnect(dsn)
  except <SomeODBCErrorHere>, e:
    print >> sys.stderr "Cannot connect to %s : %s" % (dsn, e)
    return 1
  quote = random_quote(conn.cursor())
  print format_quote(quote)
  conn.close()
  return 0

if __name__ == '__main__':
  sys.exit(main(*sys.argv))


Now for an OO version - that won't buy you much IMHO:

class SQLFortune(object):
  def __init__(self, dsn):
    self._dsn = dsn
    self._cnx = None

  @apply
  def connection():
    def fget(self):
      if self._cnx is None:
        self._cnx = odbc.DriverConnect(self.dsn)
      return self._cnx
    def fset(self, _):
      raise AttributeError("Attribute is read-only")
    return property(**locals())

  def random_quote(self):
    c = self.connection.cursor()
    c.execute ("SELECT COUNT(Quote) FROM PythonQuoteQuery")
    total_quotes = c.fetchone()
    quote_number = (random.randint(1, total_quotes[0]),)
    c.execute (
      "SELECT Author, Quote FROM PythonQuoteQuery WHERE ID=?",
       quote_number
    )
    return c.fetchone()

  def format_quote(self, quote):
    # code here
    return formatted_quote

  def close(self):
    try: self._cnx.close()
    except: pass

def main(*args):
  if len(args) < 2:
    print >> sys.stderr, "Missing dsn arg\nusage : %s dsn" % args[0]
    return 1
  dsn = args[1]
  fortune = SQLFortune(dsn)
  print fortune.format_quote(fortune.random_quote())
  fortune.close()
  return 0

if __name__ == '__main__':
  sys.exit(main(*sys.argv))


-- 
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'onurb at xiludom.gro'.split('@')])"



More information about the Python-list mailing list