I'm trying to make a simple, local database using Python where I can set values, get values, etc and I keep getting this error:
#Simple Database
#Functions include Set[name][value]
# Get[name]
# Unset[name]
# Numequalto[value]
# End
# Begin, Rollback, Commit
varlist = []
ops = []
class item:
def __init__(self,name,value):
self.name = name
self.value = value
class db:
def __init__(self):
self.varlist = []
self.ops = []
def Set(self,nm,val):
changed = False #Bool for keeping track of update
for item in varlist: #run through current list
if item.name == nm: #If the name is found
item.value = val #update the value
changed = True #found it
break #exit if found
if not changed:
newitem = item() #Create a new one and append it
newitem.name = nm
newitem.value = val
varlist.append(newitem)
def Get(key):
for item in varlist:
if item.name == key:
return item.value
break
def Unset(key):
for item in varlist:
if item.name == key:
item.value = -1
break
def Numequalto(key):
count = 0
for item in varlist:
if item.value == key:
count+=1
return count
def main():
newdb = db()
varlist=[]
comm = "" #prime it
while comm.lower() != "end":
comm = input("Command: ")
if comm.lower() == "begin":
print("----SESSION START---")
while comm.lower() != "end":
comm = input("Command: ")
part = []
for word in comm.split():
part.append(word.lower())
print(part)
if part[0].lower()=="set":
newdb.Set(part[1],part[2])
print(varlist)
elif part[0].lower()=="get":
gotten = Get(part[1])
print(gotten)
elif part[0].lower()=="unset":
Unset(part[1])
elif part[0].lower()=="numequalto":
numequal = Numequalto(part[1])
print(numequal)
print("Finished")
else:
print("--ERROR: Must BEGIN--")
if __name__ == "__main__":
main()
When I run this, and try to create a new item in my list using the command
set a 25
I get this error:
Traceback (most recent call last):
File "/Volumes/CON/LIFE/SimpleDatabase.py", line 81, in <module>
main()
File "/Volumes/CON/LIFE/SimpleDatabase.py", line 65, in main
newdb.Set(part[1],part[2])
File "/Volumes/CON/LIFE/SimpleDatabase.py", line 27, in Set
newitem = item() #Create a new one and append it
UnboundLocalError: local variable 'item' referenced before assignment
Any help would be much appreciated. I'm pretty new to Python
3 Answers 3
You have a few issues with your code:
- You are shadowing the class
itemwith a local variable of the same name. - You are using
varlistinstead ofself.varlist. - Some of your class methods doesn't recieve a
selffirst argument. - Also there is a strong convention in python to name classes with a first capital letter.
3 Comments
self.varlist and instead uses the global varlist, things will sort of work by accident).item takes two arguments in its constructor, but instead he's trying to construct it with no arguments and then set the attributes after the fact), there are a whole lot of things that are just very confusing very bad ideas (e.g., having global, local-to-main, and instance-attribute-of-db variables with the same name, using globals as instance attributes, using classic classes...).The line
for item in varlist:
shadows the class item with a local variable. So that when you get to your item() it thinks you are trying to call the local variable instead of the class. You can tell that your class item is never being constructed because it would fail as you are passing no parameters to the __init__
Also you should really call your class Item. Once I did that I got the constructor error as expected.
Comments
Not trying to be implite, just constructive here. I'm concerned that while there are comments questioning the intent to implement your own dictionary, no answer stated this forcefully. I say this only because part of Python (beyond the semantics, language, etc...) is the culture. We speak of things being 'Pythonic' for a reason - part of the value of this language is the culture. There are two aspects here to pay attention to - first, 'Batteries Included' and second, "Don't Reinvent the Wheel". You're reimplimenting the most fundamental composite (oxymoron, I know) data type in Python.
>>> a = {}
>>> a['bob'] = 1
>>> a['frank'] = 2
>>> a
{'frank': 2, 'bob': 1}
>>> del a['frank']
>>> a
{'bob': 1}
>>> del a['bob']
>>> a
{}
>>> a['george'] = 2
>>> b = len([x for x in a.values() if x == 2])
>>> b
1
And there you have it - the pythonic way of handling the functionality you're after.
If you're trying to add functionality or limitations beyond that, you're better off starting from the dict class and extending rather than rolling your own. Since Python is "duck-typed" there's a HUGE benefit to using the existing structure as your basis because it all falls into the same patterns.
itemclass is shadowed by theitemin the for-loop. You should use the CamelCase convention for your class names: name your classItemand your variableitem.sqlite3would not be helpful. Of coursedbm(or, for 2.x,anydbm) and/orshelvewould do the trick. Or, for that matter, a plain olddict, since he's just trying to store his key-value database in memory...