如何在search函数中访问window函数内的pokemon变量?
问题:封装Tkinter窗口函数后,回调函数无法访问内部变量
用户代码如下:
from tkinter import * from tkinter import ttk import requests def window(): root = Tk() root.title("Nils' Pokedex") # Styling window s = ttk.Style() s.configure('Danger.TFrame', background='red', borderwidth=5, relief='raised') ttk.Frame(root, width=200, height=200, style='Danger.TFrame').grid() mainframe = ttk.Frame(root, padding="3 3 12 12") mainframe.grid(column=0, row=0, sticky=(N, W, E, S)) root.columnconfigure(0, weight=1) root.rowconfigure(0, weight=1) pokemon = StringVar() # Search bar Creation pokemon_entry = ttk.Entry(mainframe, width=7, textvariable=pokemon) pokemon_entry.grid(column=2, row=1, sticky=(W, E)) ttk.Button(mainframe, text="Search", command=search).grid(column=3, row=3, sticky=W) # Search Button for child in mainframe.winfo_children(): child.grid_configure(padx=5, pady=5) pokemon_entry.focus() root.bind("<Return>", search) # Bind root.mainloop() def search(*args): response = requests.get("https://pokeapi.co/api/v2/pokemon/" + str(window().pokemon)) # Fetching API answer = response.json() print(answer) window()
问题核心:pokemon是window函数的局部变量,外部的search函数无法直接访问;且调用window()会重新创建新窗口,完全不是同一个实例的变量。
解决方案1:使用闭包(将search定义在window内部)
把search函数嵌套在window函数里,这样它就能直接访问window内的所有局部变量,不需要全局作用域:
from tkinter import * from tkinter import ttk import requests def window(): root = Tk() root.title("Nils' Pokedex") # Styling window s = ttk.Style() s.configure('Danger.TFrame', background='red', borderwidth=5, relief='raised') ttk.Frame(root, width=200, height=200, style='Danger.TFrame').grid() mainframe = ttk.Frame(root, padding="3 3 12 12") mainframe.grid(column=0, row=0, sticky=(N, W, E, S)) root.columnconfigure(0, weight=1) root.rowconfigure(0, weight=1) pokemon = StringVar() # Search bar Creation pokemon_entry = ttk.Entry(mainframe, width=7, textvariable=pokemon) pokemon_entry.grid(column=2, row=1, sticky=(W, E)) # 将search定义在window内部,形成闭包 def search(*args): # 获取输入框的内容,用get()方法 pokemon_name = pokemon.get().lower() if pokemon_name: try: response = requests.get(f"https://pokeapi.co/api/v2/pokemon/{pokemon_name}") response.raise_for_status() # 捕获HTTP错误 answer = response.json() print(answer) except requests.exceptions.RequestException as e: print(f"请求出错: {e}") ttk.Button(mainframe, text="Search", command=search).grid(column=3, row=3, sticky=W) # Search Button for child in mainframe.winfo_children(): child.grid_configure(padx=5, pady=5) pokemon_entry.focus() root.bind("<Return>", search) # Bind root.mainloop() window()
注意点:
- 用
pokemon.get()获取输入框的内容,而不是直接转StringVar对象 - 增加了错误处理,避免输入无效宝可梦名称时崩溃
- 转小写是因为PokéAPI的接口名称是小写的
解决方案2:使用类封装(更适合复杂应用)
把整个应用封装成一个类,所有组件和变量作为实例属性,回调函数作为实例方法,这种方式扩展性更强,适合后续添加更多功能:
from tkinter import * from tkinter import ttk import requests class PokedexApp: def __init__(self, root): self.root = root self.root.title("Nils' Pokedex") # Styling window s = ttk.Style() s.configure('Danger.TFrame', background='red', borderwidth=5, relief='raised') ttk.Frame(root, width=200, height=200, style='Danger.TFrame').grid() mainframe = ttk.Frame(root, padding="3 3 12 12") mainframe.grid(column=0, row=0, sticky=(N, W, E, S)) root.columnconfigure(0, weight=1) root.rowconfigure(0, weight=1) self.pokemon = StringVar() # 作为实例属性 pokemon_entry = ttk.Entry(mainframe, width=7, textvariable=self.pokemon) pokemon_entry.grid(column=2, row=1, sticky=(W, E)) ttk.Button(mainframe, text="Search", command=self.search).grid(column=3, row=3, sticky=W) for child in mainframe.winfo_children(): child.grid_configure(padx=5, pady=5) pokemon_entry.focus() root.bind("<Return>", self.search) def search(self, *args): pokemon_name = self.pokemon.get().lower() if pokemon_name: try: response = requests.get(f"https://pokeapi.co/api/v2/pokemon/{pokemon_name}") response.raise_for_status() answer = response.json() print(answer) except requests.exceptions.RequestException as e: print(f"请求出错: {e}") if __name__ == "__main__": root = Tk() app = PokedexApp(root) root.mainloop()
优势:
- 所有状态和逻辑都封装在类中,避免全局变量污染
- 方便后续添加新功能(比如显示宝可梦图片、属性等)
- 代码结构更清晰,维护性更强
内容的提问来源于stack exchange,提问作者Nils Edström
相关产品推荐
相关产品推荐

