By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
455,445 Members | 1,607 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 455,445 IT Pros & Developers. It's quick & easy.

help with my first use of a class

P: n/a
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.
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,

rd

--------------------------------------

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!)
if __name__ == '__main__':
if len(sys.argv) == 1:
connect()
random_quote()
print_quote()

Oct 20 '06 #1
Share this Question
Share on Google+
16 Replies


P: n/a
Whoah. At least I got the connection. I think. Maybe I can figure more
on my own. Any help appreciated.

Thanks

---------

class Connection:
def __init__(self, aDatasource):
self.db = aDatasource
self.conn = odbc.DriverConnect(self.db)
self.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 = Connection('DSN=Quotations')
c.execute ("SELECT COUNT(Quote) FROM PythonQuoteQuery")

Oct 20 '06 #2

P: n/a
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.
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,

rd

--------------------------------------

import mx.ODBC.Windows as odbc
import sys
import random

def connect():
global c
This means you want to use a global variable c which doesn't exist yet,
an example would be to save this code to a file:

#!/usr/bin/env python

c = 0
def test_global():
global c
c = 1

print c

this will print 0 when you run it
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!)

A class structure could look like - please bear in mind that I don't
know mx.ODBC.Windows - I guess it is not completely DB-API compliant,
as you don't use a connect method.

class SQLQuery(object):
"""Object which connects to the database and can execurte SQL
commands
"""
def __init__(self, conn):
"""conn is a dictionary {'serverId': XX, 'userId': YY,
'passWord': ZZ}
"""
self.connection = connect(conn['userId'], conn['passWord'],
conn['serverId'])
self.cursor = self.__connection.cursor()

def select(self, selectqry):
"""argument selectqry specifies a sql which returns data, like a
select
"""
self.cursor.execute(selectqry)
return self.cursor.fetchall()

sql = SQLQuery('serverId': 'XX', 'userId': 'YY', 'passWord': 'ZZ')
qoutes = sql.select("SELECT COUNT(Quote) FROM PythonQuoteQuery")
print quotes
if __name__ == '__main__':
if len(sys.argv) == 1:
sys.argv is a list, where the first argument is the name of the running
script, the second element is the first argument, etc.
connect()
random_quote()
print_quote()
Oct 20 '06 #3

P: n/a
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.
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,

rd

--------------------------------------

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!)
if __name__ == '__main__':
if len(sys.argv) == 1:
connect()
random_quote()
print_quote()
You really don't need classes for this, just parameters + return values.
Probably best would be to master the idea of parameters + return values
before yo move on to classes. This is called "procedural" programming.
Notice that there is no name collision because of strict python
namespaces (a good idea, according to Tim Peters).
For example:

def connect():
db='DSN=Quotations'
conn = odbc.DriverConnect(db)
c = conn.cursor()
# NOTE THE RETURN VALUE:
return c

def random_quote(c): # <== NOTE THE PARAMETER
"""
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 ...
quote_number = (random.randint(1, total_quotes[0]),)
# Select a quote where the ID matches that number
q = "SELECT Author, Quote FROM PythonQuoteQuery WHERE ID=?"
c.execute (q, quote_number)
quote = c.fetchone()
# NOTE THE RETURN VALUE:
return quote

def print_quote(quote): # <== NOTE THE PARAMETER
print quote # <== WHATEVER YOU WANT TO DO

if __name__ == '__main__':
if len(sys.argv) == 1:
c = connect() # <== NO COLLISION: NAMESPACES
quote = random_quote(c) # <== DITTO
print_quote(quote) # THERE YOU HAVE IT
James
Oct 20 '06 #4

P: n/a
Wow,

That's great, James.

Thanks. I shall put it together.

Appreciate it.

rd

Oct 20 '06 #5

P: n/a
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 'o****@xiludom.gro'.split('@')])"
Oct 20 '06 #6

P: n/a
BartlebyScrivener wrote:
Whoah. At least I got the connection. I think. Maybe I can figure more
on my own. Any help appreciated.

Thanks

---------

class Connection:
def __init__(self, aDatasource):
self.db = aDatasource
self.conn = odbc.DriverConnect(self.db)
self.conn.cursor()
This creates a cursor, that's immediatly discarded.
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 = Connection('DSN=Quotations')
c.execute ("SELECT COUNT(Quote) FROM PythonQuoteQuery")
And this will raise an AttributeError, since your (mostly useless)
Connection class doesn't define an 'execute' method.

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Oct 20 '06 #7

P: n/a
Bruno Desthuilliers wrote:
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")
make that "cursor.execute" (etc)

</F>

Oct 20 '06 #8

P: n/a
Fredrik Lundh wrote:
Bruno Desthuilliers wrote:
>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")

make that "cursor.execute" (etc)
oops, sorry - not enough coffein, I guess.
Thanks for the correction.

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Oct 20 '06 #9

P: n/a
Thanks, Bruno. Very educational.

rd

Bruno Desthuilliers wrote:
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.

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:

Now for an OO version - that won't buy you much IMHO:
Oct 20 '06 #10

P: n/a
Thank you all!

My main problem is going away from Python and programming for weeks or
months at a time, then picking up where I left off. But Python is much
better in this regard than Perl.

I appreciate the help.

rd

-----------------

Dennis Lee Bieber wrote:
If using a db-api compliant adapter, and using minimal common
features, the main thing one would have to worry about is the different
placeholders used by the adapter.

I'd be more likely to do something like

import <pick-a-db-adapteras db

and then have a class query the db connection for what type of
placeholder it uses, then modify any queries the class uses.

You might make a "class" for each database /table/, and each
instance of that class would be one record in the table. The class would
have the methods for retrieval/update/delete/insert, when given the key
value, perhaps.
--
Wulfraed Dennis Lee Bieber KD6MOG
wl*****@ix.netcom.com wu******@bestiaria.com
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: we******@bestiaria.com)
HTTP://www.bestiaria.com/
Oct 20 '06 #11

P: n/a
***********************
Your mail has been scanned by InterScan MSS.
***********************
On Friday 20 October 2006 14:34, James Stroud wrote:
You really don't need classes for this
I'm in that matter too. Doesn't classes make the main program neater?
Fundamentally OOP is the way to assemble ready objects to get a "thing"
working, rather than worry about any single code line.
Is this a concept of python?

F
Oct 20 '06 #12

P: n/a
Fulvio wrote:
***********************
Your mail has been scanned by InterScan MSS.
***********************
On Friday 20 October 2006 14:34, James Stroud wrote:
>You really don't need classes for this

I'm in that matter too. Doesn't classes make the main program neater?
Depends on the program.
Fundamentally OOP is the way to assemble ready objects to get a "thing"
working, rather than worry about any single code line.
This is more a wishful dream than reality. While it can effectively be
pretty powerful - specially with dynamic languages like Python or Ruby -
OO is by no mean magical.
Is this a concept of python?
If you mean "a concept specific to Python", well, not really - OO first
reared it's head with Simula in the sixties and matured in the seventies
with Smalltalk (which is still the reference IMHO). And it's (it->OO)
more an evolution/systematisation of concepts that already existed
before...

FWIW, I don't know if there's any truly Python-specific concept in
Python (except perhaps for the descriptor protocol, which is a somewhat
advanced topic if you're new to programming and OO...).

--
bruno desthuilliers
python -c "print '@'.join(['.'.join([w[::-1] for w in p.split('.')]) for
p in 'o****@xiludom.gro'.split('@')])"
Oct 20 '06 #13

P: n/a
Fulvio wrote:
***********************
Your mail has been scanned by InterScan MSS.
***********************
On Friday 20 October 2006 14:34, James Stroud wrote:
>You really don't need classes for this

I'm in that matter too. Doesn't classes make the main program neater?
Fundamentally OOP is the way to assemble ready objects to get a "thing"
working, rather than worry about any single code line.
Is this a concept of python?
I don't really have formal programming training, but it is increasingly
becoming my experience that OOP is but one ingredient in a good program.
It can be left out or it can be mixed with other ingredients for a nice
effect. Take for example the "file" and "open" built-ins. Calling both
creates a file object, but the latter, which is the preferred to open a
file, is actually a function rather than a class. So even the python
designers did not constrain themselves to any single "style".

I think the trick is to identify when a class would make more sense than
a collection of subroutines, etc.

James
Oct 20 '06 #14

P: n/a
On 10/20/06, James Stroud <js*****@mbi.ucla.eduwrote:
>
I don't really have formal programming training, but it is increasingly
becoming my experience that OOP is but one ingredient in a good program.
It can be left out or it can be mixed with other ingredients for a nice
effect.
Indeed. Python is a multi-paradigm programing language. If the best
solution for a problem is a class, you've got them. If on the other
hand, you just need a function, you can have one of those too - none
of this class full of static methods rubbish like you have in Java. If
a functional approach is better, Python does that.

--
Cheers,
Simon B
si***@brunningonline.net
http://www.brunningonline.net/simon/blog/
Oct 20 '06 #15

P: n/a
***********************
Your mail has been scanned by InterScan MSS.
***********************
On Saturday 21 October 2006 02:01, James Stroud wrote:
I think the trick is to identify when a class would make more sense than
a collection of subroutines
I do believe that's a bit of forecasting, in sense to determine whether a
piece of code may have a future. Usually in hobbistic term I think we can
bear with copy&pasting pieces of code across programs rather than go for a
class(es) module.
Only I remembered the mottos when I ran this,py which gives me some good
points of view.

F

Oct 21 '06 #16

P: n/a

Fulvio a écrit :
***********************
Your mail has been scanned by InterScan MSS.
***********************
On Saturday 21 October 2006 02:01, James Stroud wrote:
I think the trick is to identify when a class would make more sense than
a collection of subroutines

I do believe that's a bit of forecasting, in sense to determine whether a
piece of code may have a future.
Usually in hobbistic term I think we can
bear with copy&pasting pieces of code across programs rather than go for a
class(es) module.
OO and reuse are two orthogonal concerns. You don't need OO to reuse
code, and OO is not so much about code reuse - even if it can improve
reusability - than about how to best structure your code.

To illustrate James' POV, if you end up with half a dozen functions
working on a same well-defined data structure, then it might be time
to 'integrate' these functions and the data structure into a class.
Some other hints are when you have a small set of functions depending
on a common set of globals, or when you find yourself adding to your
functions signature too much additional params that are only meant to
be passed to other functions that themselves will pass them etc...

Copy-paste reuse should IMHO be limited to very trivial helper
functions that are not worth the pain of dependencies management...

My 2 cents

Oct 22 '06 #17

This discussion thread is closed

Replies have been disabled for this discussion.