Python-在函数外部更改变量而不返回

2024-10-05 10:47:55 发布

您现在位置:Python中文网/ 问答频道 /正文

我刚开始学习Python,就遇到了这个问题。我想从方法内部设置一个变量,但该变量在方法外部。

该方法由按钮激活。然后我想从我按下另一个按钮时设置的变量中获取值。问题是,我从方法内部放在变量中的值没有保留。我该怎么解决?

代码在下面。currentMovie是我试图更改的变量。当我用方法UpdateText()按下按钮时,它会打印出一个应该打印的随机数。但当我按下激活UpdateWatched()的按钮时,它会打印出0。所以我假设变量永远不会被设置。

import random
from tkinter import *

currentMovie = 0

def UpdateText():
    currentMovie = random.randint(0, 100)
    print(currentMovie)

def UpdateWatched():
    print(currentMovie)

root = Tk()
root.title("MovieSelector9000")
root.geometry("900x600")
app = Frame(root)
app.grid()
canvas = Canvas(app, width = 300, height = 75)
canvas.pack(side = "left")
button1 = Button(canvas, text = "SetRandomMovie", command = UpdateText)
button2 = Button(canvas, text = "GetRandomMovie", command = UpdateWatched)
button1.pack(anchor = NW, side = "left")
button2.pack(anchor = NW, side = "left")
root.mainloop()

Tags: 方法importappdefrandomrootleft按钮
3条回答

这里有一个简单但肮脏的解决方案:使用可变变量。

而不是

currentMovie = 0

def UpdateText():
    currentMovie = random.randint(0, 100)
    print(currentMovie)

可以对currentMovie使用单单元格列表,并将其作为(默认)参数传递给UpdateText():

currentMovie = [0]

def UpdateText(cM=currentMovie): # The default value will 'bind' currentMovie to this argument
    cM[0] = random.randint(0, 100) # This will change the *contents* of the variable
    print(cM[0]) # I used a different name for the parameter to distinguish the two

UpdateText() # Calls UpdateText, updating the contents of currentMovie with a random number

请注意,即使使用新列表,也将currentMovie本身(而不是其内容)设置为新值将导致UpdateText()停止更新currentMovie,除非def块再次运行。

currentMovie = [0]

def UpdateText(cM=currentMovie): # The default value will 'bind' currentMovie to this argument
    cM[0] = random.randint(0, 100) # This will change the *contents* of the list
    print(cM[0]) # I used a different name for the parameter to distinguish the two

currentMovie = 3 # UpdateText() will no longer affect this variable at all

# This will thus not throw an error, since it's modifying the 'old' currentMovie list:
UpdateText() # The contents of this list can also no longer be accessed

如果您正在快速而肮脏地构建一些东西,并且不想构建类,那么这是一个更方便的技巧;我发现Python非常适合这样的东西,所以我认为尽管有其他答案,但这仍然值得分享。

不过,为了更严肃的目的,创建bruno's answer中的类几乎肯定会更好。

使用global修改函数外部的变量:

def UpdateText():
    global currentMovie
    currentMovie = random.randint(0, 100)
    print(currentMovie)

但是,不要使用global。通常是code smell

下面是一个简单的(python 2.x)示例,说明如何1not使用globals和2使用(简单)域模型类。

要点是:首先应该独立于用户界面设计域模型,然后编写调用域模型的用户界面代码。在本例中,您的UI是一个Tkinter GUI,但是同一个域模型应该能够使用命令行UI、web UI或其他东西。

注意:对于python 3.x,将Tkinter替换为tkinter(小写),您可以去掉Modelobject基类。

import random
from Tkinter import *


class Model(object):
    def __init__(self):
        self.currentMovie = 0

    def UpdateCurrentMovie(self):
        self.currentMovie = random.randint(0, 100)
        print(self.currentMovie)

    def UpdateWatched(self):
        print(self.currentMovie)

    def ExampleWithArgs(self, arg):
        print("ExampleWithArg({})".format(arg))


def main():
    model = Model()
    root = Tk()
    root.title("MovieSelector9000")
    root.geometry("900x600")
    app = Frame(root)
    app.grid()
    canvas = Canvas(app, width = 300, height = 75)
    canvas.pack(side = "left")
    button1 = Button(canvas, text = "SetRandomMovie", command=model.UpdateCurrentMovie)
    button2 = Button(canvas, text = "GetRandomMovie", command=model.UpdateWatched)
    button3 = Button(canvas, text = "ExampleWithArg", command=lambda: model.ExampleWithArgs("foo"))
    button1.pack(anchor = NW, side = "left")
    button2.pack(anchor = NW, side = "left")
    button3.pack(anchor = NW, side = "left")
    root.mainloop()

if __name__ == "__main__":
    main()

相关问题 更多 >

    热门问题