当列表中有两个元素且索引为1时,为什么会说索引超出范围

2024-04-25 23:44:39 发布

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

这是我的代码:

from tkinter import Label, Button, Tk, Toplevel
import sqlite3

db = sqlite3.connect('people.db')
sql = db.cursor()


def person_viewer(person: str) -> None:
    person_viewing_window: Toplevel = Toplevel()
    person_viewing_window.title(person)
    Label(person_viewing_window, text=person).pack()


root: Tk = Tk()
root.title("People")
root.geometry('800x600')
count: int = 0
people: list = []
for person in sql.execute('SELECT first_name FROM people;'):
    people.append(person)
    Button(root, text=person, command=lambda: person_viewer(people[count])).pack()
    count += 1
root.mainloop()

我使用VS代码的调试功能来确保索引确实没有超出范围,并发现它没有超出范围。索引为1,列表长度为2。这意味着列表中的第二个元素,因为Python是基于零的索引。具体误差如下:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\me\AppData\Local\Programs\Python\Python38-32\lib\tkinter\__init__.py", line 1883, in __call__
    return self.func(*args)
  File "c:\Users\me\Real Documents\people.pyw", line 21, in <lambda>
    Button(root, text=person, command=lambda: person_viewer(people[count])).pack()
IndexError: list index out of range

如错误所示,该错误仅在单击任何按钮时触发

有趣的是,在PyCharm Community Edition 2020.2中运行时,它给出了一个完全不同的错误:

C:\Users\me\AppData\Local\Programs\Python\Python38-32\python.exe "C:/Users/me/Real Documents/people.pyw"
Traceback (most recent call last):
  File "C:/Users/me/Real Documents/people.pyw", line 19, in <module>
    for person in sql.execute('SELECT first_name FROM people;'):
sqlite3.OperationalError: no such table: people

从空闲、Visual Studio代码或py.exe运行时不会发生这种情况

我不明白为什么索引是越界的,而且,为什么PyCharm给出了一个不同的、绝对错误的错误。作为记录,以下是我的SQL:

BEGIN TRANSACTION;

CREATE TABLE people (id INTEGER PRIMARY KEY NOT NULL AUTOINCREMENT, first_name TEXT NOT NULL, last_name TEXT NOT NULL);

INSERT INTO people VALUES(1,'My','Name');
INSERT INTO people VALUES(2,"Sister's",'Name');

COMMIT;

Tags: 代码nameindbcount错误buttonroot
1条回答
网友
1楼 · 发布于 2024-04-25 23:44:39

如果希望lambda函数引用循环中当前正在考虑的person,可以将该值复制到lambda函数内的专用变量

这样做的方法如下:

command=(lambda p=person: person_viewer(p))

将当前值person绑定到正在定义的函数中参数p的默认值,然后对该参数调用person_viewer

在这方面:

for person in sql.execute('SELECT first_name FROM people;'):
    people.append(person)
    Button(root, text=person, command=(lambda p=person: person_viewer(p))).pack()
    count += 1

相关问题 更多 >