Функция exec не видит переменную python
День добрый, необходимо создавать множество кнопок, проблема в том, что без возведения в функцию всё работает отлично, но как только я возвожу в функцию:
NameError: name 'id_button_01' is not defined
M = {1: '01', 2: 'M', 4: 0}
def func(E):
exec(f"id_button_{E} = tk.Button(window, image=M_img, command=pressed(M[4], M[2], id_button_{E}))")
exec(f"id_button_{E}.place(x=0, y=0)")
func(M[1])
Помогите, в чём проблема? Или как можно написать данную функцию без exec? Сильно не пинайте, совсем ещё мал и неопытен. Заранее благодарю.
Ответы (3 шт):
Дело в том, что exec не может влиять на глобальные переменные. Попробуйте
M = {1: '01', 2: 'M', 4: 0}
def func(E):
exec(f"id_button_{E}") = tk.Button(window, image=M_img, command=pressed(M[4], M[2], id_button_{E}))
exec(f"id_button_{E}").place(x=0, y=0)
func(M[1])
Ошибка возникала не из-за exec а по причине того что в конструктор кнопки передавалась еще не инициализированная переменная id_button_N, при разбитии на 2 комманды все работает. Так же я использовал лямбду для инициализации command.
import tkinter as tk
from tkinter import messagebox as mb
M = {1: '01', 2: 'M', 4: 0}
window = tk.Tk()
M_img=None
def pressed(a,b,c):
mb.showinfo(title="'"+str(a)+"'", message=b)
def func(E):
exec(f"""id_button_{E} = tk.Button(window, image=M_img)
id_button_{E}['command'] = lambda:pressed(M[4], M[2], id_button_{E})""",
globals())
exec(f"id_button_{E}.place(x=0, y=0)", globals())
func(M[1])
window.mainloop()
Вот небольшой пример как передавать внутрь exec переменные:
N = 100;
ns_globals = {'N':N}
ns_locals = {'K': 20}
exec('N += K\nprint("№1", N)', ns_globals, ns_locals)
print('№2', N)
exec('N += N', globals())
print("№3", N)
выведет:
№1 120
№2 100
№3 200
exec(obj[, globals[, locals]])-> None
obj : Строка кода, либо объект кода. Поддерживается ввод данных из файлов (считываются до EOF). Если передана строка, она разбирается в набор инструкций, который потом исполняется (если отсутствуют синтаксические ошибки). Если передан объект кода, то он исполняется.
globals : Ожидается dict. Словарь глобального пространства, относительно которого следует исполнить код. Если locals не передан, будет использован globals. Если словарь не имеет значения по ключу __builtins__, на это место вставляется ссылка на значение аналогичного атрибута глобального пространства. Модифицировав __builtins__ словаря передаваемого в функцию, вы можете контролировать, какие какие из встроенных инструментов будут доступны коду.
locals : Ожидается объект-отображение (например, dict). Локальное пространство, в котором следует исполнить код.
Функциям exec() и eval() можно передавать результаты функций globals() и locals().
Или как можно написать данную функцию без exec?
Используйте словарь.
Например:
M = {1: '01', 2: 'M', 4: 0}
id_button = dict()
def func(E):
id_button[E] = tk.Button(window, image=M_img, command=pressed(M[4], M[2], id_button[E]))
id_button[E].place(x=0, y=0)
func(M[1])
Тогда все кнопки, добавленные через func, можно будет получить из словаря id_button