Почему он говорит, что индекс выходит за пределы, когда в списке два элемента, а индекс равен 1 - PullRequest
0 голосов
/ 05 августа 2020

Это мой код:

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 Code, чтобы убедиться, что индекс действительно не выходит за границы, и обнаружил, что это не так. Индекс был равен 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

Этого не происходит при запуске из IDLE, Visual Studio Code или 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;

1 Ответ

1 голос
/ 05 августа 2020

Если вы хотите, чтобы ваша лямбда-функция ссылалась на person, который в настоящее время рассматривается в вашем l oop, вы можете скопировать это значение в выделенную переменную внутри лямбда-функции.

Способ сделать это будет примерно так:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...