Python中函数向菜单传递变量

0 投票
2 回答
986 浏览
提问于 2025-05-01 09:51

我有一个叫做 menu() 的函数,它用来创建一个菜单,让我可以选择不同的功能。下面是这个函数的代码。

def menu():
    x = raw_input("WOOF! What can POODLE fetch for you? ('--nothing' to exit): ")
    if x == "--nothing":
            sys.exit(0)
    elif x == "--build":
            populateCrawled(toCrawl)
            graph = buildGraph(crawled)
            index = buildIndex(graph)
            ranks = computeRanks(graph)
            menu()
    elif x == "--dump":
            saveFile(index, "index.txt")
            saveFile(graph, "graph.txt")
            saveFile(ranks, "ranks.txt")
            menu()
    elif x == "--restore":
            index = loadFile("index.txt")
            graph = loadFile("graph.txt")
            ranks = loadFile("ranks.txt")
            menu()
    elif x == "--print":
            print graph
            print index
            print ranks
            menu()
    elif x == "--help":
            print "WOOF! POODLE Help Options"
            print "--build     Create the POODLE database"
            print "--dump      Save the POODLE database"
            print "--restore   Retrieve the POODLE database"
            print "--print     Show the POODLE database"
            print "--help      Show this help information"
            menu()
    elif x == "--search":
            search(index, rankablePages)
    else:
            print "Help option not found"
            menu()

seed = raw_input("Please enter the seed URL: ")
testSeed = "https://dunluce.infc.ulst.ac.uk/d11ga2/COM506/AssignmentB/test_index.html"
seed = testSeed
toCrawl=[seed]
crawled, graph, index, rankablePages = [], {}, {}, {}
MAX_DEPTH = 10
menu()

这些变量和字典都是全局声明的,但当我输入“--build”时,它确实能成功构建。但是当我接着输入“--print”时,就出现了一个错误,提示“UnboundLocalError: local variable 'graph' referenced before assignment”,意思是说在赋值之前就引用了这个局部变量 'graph'。

不过,如果我在构建之后立刻打印这些字典,它们是可以正常显示的。问题出在当 menu() 函数重新加载时,它丢失了这些值。我是不是应该使用一个循环,还是说我需要传递一些参数呢?

暂无标签

2 个回答

0

你应该把图(以及菜单需要用到的其他变量)声明为全局变量:

def menu():
    global graph

    #rest of the code

你可以在这里了解更多关于全局变量的信息。

1

这些变量虽然是全局声明的,但这并没有什么帮助(不过要注意,你其实并没有真正把 ranks 定义为全局变量……),因为它们在局部也被声明了,局部的名字会遮住全局的名字。

每当你在一个函数内部写 spam = eggs 时,spam 就变成了一个局部变量。在这个函数里,任何地方出现的 spam 都指的是这个局部变量。

如果你想让某个变量是全局的,但又想给它赋值,你需要使用一个 global 声明。所以:

def menu():
    global graph, index, ranks
    # the rest of your code

不过,通常来说,最好的办法是停止使用全局变量。

一个选择是创建一个 来保存你的状态,把 menu 作为这个类的方法,并把 graph 和其他相关的变量作为这个类实例的属性。

但这里还有一个更简单的选择。你需要这些变量是全局的唯一原因是因为 menu 正在递归调用自己来模拟一个循环。这样做在 Python 中本身就不是个好主意,原因还有很多。(比如,如果你在菜单里转了大约 999 次,你会遇到递归错误。)如果你直接使用循环,而不是试图伪装成循环,你就可以使用局部变量了:

def menu(graph, index, ranks):
    while True:
        # the rest of your code except the menu() calls

# ...
crawled, graph, index, rankablePages = [], {}, {}, {}
menu(graph, index, ranks)

撰写回答