簡體   English   中英

str AttributeError:“ str”對象沒有屬性“ set”(更新標簽)

[英]str AttributeError: 'str' object has no attribute 'set' (updating label)

這是一個簡單的數學游戲。 感興趣的功能是checkAnswer() 我正在嘗試更新label1以便標簽以新的str更新,而不是連續打印多個標簽。

錯誤:

AttributeError:'str'對象沒有屬性'set'

from tkinter import *

from random import randint

num1 = 0
num2 = 0
userAnswer = 0
answer = 0
score = 0
labeltext = ""

#PROGRAM FUNCTIONS
def question():
    global num1, num2
    global answer
    num1 = randint(1,10)
    num2 = randint(1,10)
    question = Label(text = "What is " + str(num1)+ " + " + str(num2) + "?").pack()
    answer = num1+num2
    print(answer) #testing purposes

def userAnswer():
    global userAnswer
    userAnswer = IntVar()
    entry = Entry(root, textvariable = userAnswer).pack()
    submit = Button(root, text = "submit", command = checkAnswer).pack()

def checkAnswer():
    global labeltext
    print(userAnswer.get())
    if userAnswer == answer:
        labeltext.set("good job")
        score += 1
    elif userAnswer != answer:
        labeltext.set("oh no")
    labeltext = StringVar()
    label1 = Label(root, textvariable = labeltext).pack()

#INTERFACE CODE
root = Tk()

question()
userAnswer()
root.mainloop()

之所以收到AttributeError是因為最初將字符串""綁定到全局名稱labeltext ,而Python字符串沒有.set方法。 (這是沒有意義的,因為Python字符串是不可變的)。 您最終將Tkinter StringVar綁定到labeltext ,並且StringVar 確實具有.set方法,但是您的代碼在已經嘗試在純Python字符串上調用.set之后才這樣做。

您命名為userAnswerIntVar也會發生類似的問題。 那還有另一個問題:它的名稱與您的一個功能沖突。 你不能那樣做!

這是代碼的修復版本,還有一些其他小的更改。 無需在這些StringVarIntVar上使用global指令,因為您只是在調用這些對象的方法。 僅在需要對全局對象執行賦值時才需要global ,只需訪問全局的現有值或調用其方法之一就不需要global指令。

from tkinter import *
from random import randint

#PROGRAM FUNCTIONS
def question():
    global true_answer
    num1 = randint(1,10)
    num2 = randint(1,10)
    Label(text="What is " + str(num1)+ " + " + str(num2) + "?").pack()
    true_answer = num1 + num2
    print(true_answer) #testing purposes

def answer():
    Entry(root, textvariable=userAnswer).pack()
    Button(root, text="submit", command=checkAnswer).pack()

def checkAnswer():
    global score
    print(userAnswer.get()) #testing purposes
    if userAnswer.get() == true_answer:
        labeltext.set("good job")
        score += 1
    else:
        labeltext.set("oh no")
    label1 = Label(root, textvariable=labeltext).pack()

#INTERFACE CODE
root = Tk()

true_answer = 0
score = 0

userAnswer = IntVar()
labeltext = StringVar()

question()
answer()
root.mainloop()

但是,該代碼仍然存在幾個問題。 它只能問一個問題。 而且,每當您單擊“提交”按鈕時,它都會添加一個新的Label小部件,我認為您並不是真正想要的。

使用全局變量不是一個好主意。 它們破壞了模塊化,這使代碼更難以理解,也難以修改和重用。

這是程序的增強版本,它將所有內容放入一個類中,因此我們可以使用實例屬性代替全局變量。

此版本詢問多個問題。 它沒有“提交”按鈕,而是當用戶單擊主鍵盤或數字小鍵盤上的Enter / Return鍵時,將自動提交問題。

import tkinter as tk
from random import randint

class Quiz(object):
    def __init__(self):
        root = tk.Tk()

        # The question
        self.question_var = tk.StringVar()
        tk.Label(root, textvariable=self.question_var).pack()

        # The answer
        self.user_answer_var = tk.StringVar()
        entry = tk.Entry(root, textvariable=self.user_answer_var)
        entry.pack()
        # Check the answer when the user hits the Enter key,
        # either on the main keyboard or the numeric KeyPad
        entry.bind("<Return>", self.check_answer)
        entry.bind("<KP_Enter>", self.check_answer)
        self.true_answer = None

        # The response
        self.response_var = tk.StringVar()
        self.score = 0
        tk.Label(root, textvariable=self.response_var).pack()

        # Ask the first question
        self.ask_question()
        root.mainloop()

    def ask_question(self):
        num1 = randint(1, 10)
        num2 = randint(1, 10)
        self.question_var.set("What is {} + {}?".format(num1, num2))
        self.true_answer = num1 + num2
        #print(self.true_answer) #testing purposes

    def check_answer(self, event):
        user_answer = self.user_answer_var.get()
        #print(user_answer) #testing purposes

        if int(user_answer) == self.true_answer:
            text = "Good job"
            self.score += 1
        else:
            text = "Oh no"
        self.response_var.set('{} Score={}'.format(text, self.score))

        # Clear the old answer and ask the next question
        self.user_answer_var.set('')
        self.ask_question()

Quiz()

請注意import tkinter as tk語句。 from tkinter import *相比,使用這種形式好得多,因為該“星號”導入會將130個名稱轉儲到您的名稱空間中,這很麻煩,並且可能導致名稱沖突,特別是如果您與其他模塊一起進行星號導入。 import tkinter as tk形式需要您進行更多輸入,但是這也使代碼更易於閱讀,因為很明顯哪些名稱來自Tkinter。

我還更改了變量和類方法(函數)的名稱,以使它們符合Python PEP-0008樣式指南。

可以進行各種進一步的增強。 特別是,此代碼無法正常處理不是有效整數的用戶輸入。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM