Reputation: 8292
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?
Upvotes: 0
Views: 211
Reputation: 3215
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()
Upvotes: 0
Reputation: 8571
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).
Upvotes: 1
Reputation: 2261
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
Upvotes: 1
Reputation: 184191
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(...)
Upvotes: 1
Reputation: 39451
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()
Upvotes: 1