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

时间:2016-10-04 15:03:19

标签: 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()

3 个答案:

答案 0 :(得分:5)

这是一个简单的(python 2.x)示例,说明如何1 使用全局变量,2使用(简单)域模型类。

重点是:您应该首先独立于用户界面设计域模型,然后编写调用域模型的用户界面代码。在这种情况下,您的UI是一个Tkinter GUI,但相同的域模型应该能够使用命令行UI,Web UI或其他任何内容。

注意:对于python 3.x,将Tkinter替换为tkinter(小写),您可以删除object的{​​{1}}基类。

Model

答案 1 :(得分:2)

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

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

但是,请勿使用global。通常是code smell

答案 2 :(得分:1)

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

代替

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中那样创建类会更好。