用Python创建带有自定义命令的数据库

3

我正在尝试使用Python创建一个简单的本地数据库,可以设置值、获取值等,但是一直出现以下错误:

#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()

当我运行此代码并尝试使用命令在列表中创建新项时,会出现以下情况:
set a 25

我收到了这个错误信息:


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

非常感谢您的帮助。我对Python还比较陌生。


1
item类被for循环中的item所遮蔽。您应该使用CamelCase约定来命名您的类名:将您的类命名为Item,变量命名为item - Waleed Khan
你为什么要自己编写数据库而不使用Python附带的aqlite3模块呢? - James Thiele
请将您的类命名为首字母大写,这样可以避免我一开始感到困惑。 - cmd
1
@JamesThiele他并不是在尝试自己编写SQL数据库,而是在尝试自己编写键值数据库,因此sqlite3并没有什么帮助。当然,dbm(或者对于2.x版本,anydbm)和/或者shelve可以解决问题。或者,说实话,一个普通的dict也可以,因为他只是想将键值数据库存储在内存中... - abarnert
@WaleedKhan是正确的。真不敢相信我错过了/没有想到这么简单的事情。 - raider64
1
阅读PEP8应该有助于您的编码风格。 - cmd
3个回答

1

不是要无礼,只是想提出建设性意见。我担心虽然有评论质疑实现自己的字典的意图,但没有一个回答明确地表态。我之所以这样说,是因为Python(超越语义、语言等方面)的一部分是文化。我们谈论“Pythonic”的东西是有原因的——这种语言的价值之一就在于文化。这里需要注意两个方面——首先,“电池内置”,其次,“不要重复造轮子”。你正在重新实现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

以上就是处理所需功能的Python方式。

如果您想添加功能或限制,最好从字典类开始扩展,而不是自己编写。由于Python采用“鸭子类型”,因此使用现有结构作为基础具有巨大的优势,因为它们都遵循相同的模式。


1

这行

for item in varlist: 

使用本地变量遮蔽了类 item。所以当你到达你的item()时,它认为你正在尝试调用本地变量而不是类。你可以看出你的类 item 没有被构建,因为你没有向 __init__ 传递任何参数。
另外,你应该真正称呼你的类为 Item。一旦我这样做了,我就像预期的那样得到了构造函数错误。

1

您的代码存在以下几个问题:

  1. 您在本地变量中使用了与类 item 相同的名称,导致该类被遮蔽。
  2. 您使用了 varlist 而不是 self.varlist
  3. 您的一些类方法没有接收到第一个参数 self
  4. 此外,在 Python 中有一个强烈的惯例,即将类命名为首字母大写。

谁给这个贴踩了踩,为什么?除了可能技术上的问题#3以外,所有点都是正确的(只要原帖始终忽略 self.varlist 并使用全局的 varlist,事情会有点意外地好转)。 - abarnert
话虽如此,这并不是一个详尽的列表。快速浏览一下,除了明显的错误(例如,item在其构造函数中需要两个参数,但他却试图在没有参数的情况下构造它,然后在事后设置属性),还有很多非常令人困惑的非常糟糕的想法(例如,具有相同名称的全局变量、局部变量-main和实例属性-db,使用全局变量作为实例属性,使用经典类...)。 - abarnert
2不一定是问题,它将使用全局变量列表,但很难确定他的意思是否是这样,因为程序中有3个不同的变量列表。 - cmd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接