0

I have a script that I had originally left as one long function.

#! /usr/bin/env python
import mechanize
from BeautifulSoup import BeautifulSoup
import sys
import sqlite3

def dictionary(word):
    br = mechanize.Browser()
    response = br.open('http://www.dictionary.reference.com')
    br.select_form(nr=0)
    br.form['q'] = word 
    br.submit()
    definition = BeautifulSoup(br.response().read())
    trans = definition.findAll('td',{'class':'td3n2'})
    fin = [i.text for i in trans]
    query = {}
    word_count = 1
    def_count = 1
    for i in fin: 
        query[fin.index(i)] = i
    con = sqlite3.connect('/home/oberon/vocab_database/vocab.db')
    with con:
        spot = con.cursor()
        spot.execute("SELECT * FROM Words")
        rows = spot.fetchall()
        for row in rows:
            word_count += 1
        spot.execute("INSERT INTO Words VALUES(?,?)", (word_count,word))
        spot.execute("SELECT * FROM Definitions")
        rows = spot.fetchall()
        for row in rows:
            def_count += 1
        for q in query:
            spot.execute("INSERT INTO Definitions VALUES(?,?,?)", (def_count,query[q],word_count))
            def_count += 1
    return query

print dictionary(sys.argv[1])

Now, I wanted to practice OOP form by creating a class. I thought it would be best to separate this into at least a couple of functions too.

I came up with:

#! /usr/bin/env python
import mechanize
from BeautifulSoup import BeautifulSoup
import sys
import sqlite3


class Vocab:
    def __init__(self):
        self.word_count = 1
        self.word = sys.argv[1] 
        self.def_count = 1
        self.query = {}

    def dictionary(self,word):
        self.br = mechanize.Browser()
        self.response = self.br.open('http://www.dictionary.reference.com')
        self.br.select_form(nr=0)
        self.br.form['q'] = word 
        self.br.submit()
        self.definition = BeautifulSoup(self.br.response().read())
        self.trans = self.definition.findAll('td',{'class':'td3n2'})
        self.fin = [i.text for i in self.trans]
        for i in self.fin: 
            self.query[self.fin.index(i)] = i
        return self.query

    def word_database(self):
        self.con = sqlite3.connect('/home/oberon/vocab_database/vocab.db')
        with self.con:
            self.spot = self.con.cursor()
            self.spot.execute("SELECT * FROM Words")
            self.rows = self.spot.fetchall()
            for row in self.rows:
                self.word_count += 1
            self.spot.execute("INSERT INTO Words VALUES(?,?)", (self.word_count,self.word))
            self.spot.execute("SELECT * FROM Definitions")
            self.rows = self.spot.fetchall()
            for row in self.rows:
                self.def_count += 1
            for q in self.query:
                self.spot.execute("INSERT INTO Definitions VALUES(?,?,?)", (self.def_count,self.query[q],self.word_count))
                self.def_count += 1



Vocab().dictionary(sys.argv[1])

I know that on the last line when I call Vocab().dictionary(sys.argv[1]) this is only going to run the dictionary method. I am trying to figure out how to invoke the word_database method everytime I run the script still.

Is this the wrong way to go about this? Should I of just left these methods as just one large method?

1
  • 1
    just call your method word_database in your other method Commented Aug 14, 2012 at 23:49

5 Answers 5

1

It looks fine as a script to me. The only real question is why you do

for row in rows:
        word_count += 1

instead of

word_count += len(rows)

As for your question, you call word_database by doing

self.word_database()
Sign up to request clarification or add additional context in comments.

1 Comment

For the first part, this the first time I've worked in sqlite3 into a script and it took me a minute to think how to give the word an 'id' each time I ran it. You are totally right, thanks :)! The second part, you're saying just add that into the dictionary method?
1

I'm not really sure there is any advantage to it being a class, but if you want to call multiple methods of an instance, you will need to assign a name to the instance.

vocab = Vocab()
vocab.dictionary(...)
vocab.word_database(...)

1 Comment

I was thinking there isn't much advantage here too, with not a whole lot of code that it would be useful with. I was really wanting to practice the 'form'.
1

You just need to call word_database at the same point you would have in the original script.

def dictionary(self,word):
    self.br = mechanize.Browser()
    self.response = self.br.open('http://www.dictionary.reference.com')
    self.br.select_form(nr=0)
    self.br.form['q'] = word 
    self.br.submit()
    self.definition = BeautifulSoup(self.br.response().read())
    self.trans = self.definition.findAll('td',{'class':'td3n2'})
    self.fin = [i.text for i in self.trans]
    for i in self.fin: 
        self.query[self.fin.index(i)] = i

    # Continue the script...
    self.word_database()

    return self.query

Comments

1

A couple of things:

First, you don't need to make all variables self.var_name just because you're wrapping them in a class. If the variable isn't needed after the function call finishes, just use local variables.

Second, to get word_database to have been called each time Vocab uses dictionary adding self.word_database() to your init function __init__(self, word). This will ensure those features are always available.

Third, if you're just going to treat the object as a script and do Vocab().dictionary(word) you're probably better off with not using a class structure. If you plan on computing some of the work with Vocab() and then doing other work incrementally (calling dictionary repeatedly) then keep the class structure. But the way you're using it currently is like a function call. (If you keep function call semantics you should at least break that original function into smaller parts).

1 Comment

I was thinking of adding on my original question into a couple of separate questions for that reason especially. In particular how to clean up the code and use best/better form. Thanks again,very helpful.
0

I'd recommend first refactoring without going object-oriented. You don't gain anything by making a class. Just define your two methods, and at the end:

dictionary(sys.argv[1)
word_database()

1 Comment

I was aware this isn't an ideal situation to make it into objected-oriented code, just wanted practice some. Thank you for answering, though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.