Python调用class方法时看不到self.attribute
Python self.attribute cannot be seen when calling class method
我遇到了与我正在创建的 TKinter GUI 相关的问题,但该问题不一定特定于此库。
背景
我目前正处于 python 自学课程的高级阶段。我所在的学习模块涵盖了用于创建交互式 GUI 的 TKinter。我正在制作一个游戏,必须在尽可能快的时间内连续点击随机生成的编号按钮。
简介:https://edube.org/learn/pcpp1-4-gui-programming/lab-the-clicker
问题
在我的class、game_grid下,我创建了一个实例变量; 'self.holder',一个包含 25 个条目的 {Key : TkinterButtonObject} 形式的字典
在 class 方法中调用此实例变量时,出现以下错误:
AttributeError: 'game_grid' object has no attribute 'holder'
- 我在class init下有打印语句,证明这个属性已经创建成功。我已经确保我的间距和制表符都没有问题,并且已经尝试了这个变量的每个位置,包括用作 class 变量和全局变量都无济于事 - 因为它是一个半复杂的对象。我看不出它应该有什么不同,但任何想法都将不胜感激。我也知道这可以在没有 classes 的情况下完成,但我正在尝试在我的所有程序中采用 DRY 原则和正交性。
提前致谢。
完整代码:
import tkinter as tk
from tkinter import*
import random
from tkinter import messagebox
import time
win = tk.Tk()
class game_grid:
def __init__(self, win):
self.last_number = 0
self.number_buttons = {}
self.row_count = 0
self.column_count = 0
#Generate a list of 25 random numbers
self.number_list = random.sample(range(0, 999), 25)
#Puts the numbers in a dictionary (number : buttonobject)
self.holder = {i: tk.Button(win, text = str(i), command = game_grid.select_button(self, i)) for i in self.number_list}
#pack each object into window by iterating rows and columns
for key in self.holder:
self.holder[key].grid(column = self.column_count, row = self.row_count)
if self.column_count < 4:
self.column_count += 1
elif self.column_count == 4:
self.column_count = 0
self.row_count += 1
print(self.holder)
def select_button(self, number):
if number > self.last_number:
self.holder[number].config(state=tk.DISABLED)
self.last_number = number
else:
pass
class stopclock():
def __init__(self):
#Stopclock variable initialisation
self.time_begin = 0
self.time_end = 0
self.time_elapsed= 0
def start(self):
if self.time_begin == 0:
self.time_begin = time.time()
return("Timer started\nStart time: ", self.time_begin)
else:
return("Timer already active")
def stop(self):
self.time_end = time.time()
self.time_elapsed = time_end - time_begin
return("Timer finished\nEnd time: ", time_begin,"\nTime Elapsed: ", time_elapsed)
play1 = game_grid(win)
win.mainloop()
也许你的意思是:
command = self.select_button(self, i)
更新:
虽然来自研究:How to pass arguments to a Button command in Tkinter?
应该是:
command = lambda i=i: self.select_button(i)
您从 holder
的字典理解中调用 select_button
。 select_button
然后尝试使用 holder
,但尚未定义。您不想实际调用 select_button
,而是为按钮分配一个功能,例如:
self.holder = {i: tk.Button(window, text=str(i), command=lambda i=i: self.select_button(i)) for i in self.number_list}
我遇到了与我正在创建的 TKinter GUI 相关的问题,但该问题不一定特定于此库。
背景
我目前正处于 python 自学课程的高级阶段。我所在的学习模块涵盖了用于创建交互式 GUI 的 TKinter。我正在制作一个游戏,必须在尽可能快的时间内连续点击随机生成的编号按钮。
简介:https://edube.org/learn/pcpp1-4-gui-programming/lab-the-clicker
问题
在我的class、game_grid下,我创建了一个实例变量; 'self.holder',一个包含 25 个条目的 {Key : TkinterButtonObject} 形式的字典
在 class 方法中调用此实例变量时,出现以下错误:
AttributeError: 'game_grid' object has no attribute 'holder'
- 我在class init下有打印语句,证明这个属性已经创建成功。我已经确保我的间距和制表符都没有问题,并且已经尝试了这个变量的每个位置,包括用作 class 变量和全局变量都无济于事 - 因为它是一个半复杂的对象。我看不出它应该有什么不同,但任何想法都将不胜感激。我也知道这可以在没有 classes 的情况下完成,但我正在尝试在我的所有程序中采用 DRY 原则和正交性。
提前致谢。
完整代码:
import tkinter as tk
from tkinter import*
import random
from tkinter import messagebox
import time
win = tk.Tk()
class game_grid:
def __init__(self, win):
self.last_number = 0
self.number_buttons = {}
self.row_count = 0
self.column_count = 0
#Generate a list of 25 random numbers
self.number_list = random.sample(range(0, 999), 25)
#Puts the numbers in a dictionary (number : buttonobject)
self.holder = {i: tk.Button(win, text = str(i), command = game_grid.select_button(self, i)) for i in self.number_list}
#pack each object into window by iterating rows and columns
for key in self.holder:
self.holder[key].grid(column = self.column_count, row = self.row_count)
if self.column_count < 4:
self.column_count += 1
elif self.column_count == 4:
self.column_count = 0
self.row_count += 1
print(self.holder)
def select_button(self, number):
if number > self.last_number:
self.holder[number].config(state=tk.DISABLED)
self.last_number = number
else:
pass
class stopclock():
def __init__(self):
#Stopclock variable initialisation
self.time_begin = 0
self.time_end = 0
self.time_elapsed= 0
def start(self):
if self.time_begin == 0:
self.time_begin = time.time()
return("Timer started\nStart time: ", self.time_begin)
else:
return("Timer already active")
def stop(self):
self.time_end = time.time()
self.time_elapsed = time_end - time_begin
return("Timer finished\nEnd time: ", time_begin,"\nTime Elapsed: ", time_elapsed)
play1 = game_grid(win)
win.mainloop()
也许你的意思是:
command = self.select_button(self, i)
更新:
虽然来自研究:How to pass arguments to a Button command in Tkinter?
应该是:
command = lambda i=i: self.select_button(i)
您从 holder
的字典理解中调用 select_button
。 select_button
然后尝试使用 holder
,但尚未定义。您不想实际调用 select_button
,而是为按钮分配一个功能,例如:
self.holder = {i: tk.Button(window, text=str(i), command=lambda i=i: self.select_button(i)) for i in self.number_list}