Уведомления

Группа в Telegram: @pythonsu

#1 Ноя. 19, 2017 17:38:27

winmasta
Зарегистрирован: 2017-10-03
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Как создать переменную из словаря с именем ключа ?

Задавал тут вопрос про tkinter и как конструировать окна с произвольными полями ввода, но тему найти не могу, видимо удалена. В общем накидал тут конструктор окна:

 #!/usr/bin/python3
#coding=utf8
from tkinter import Tk
from tkinter import Label
from tkinter import Entry
from tkinter import Button
def calculate(**kwargs):
    for key, value in kwargs.items():
        try:
            locals()[key] = value["type"](value["value"].get())
        except ValueError:
            locals()[key] = value["type"](value["default"])
    print(locals())
    print(mu)
def make_gui(title, **kwargs):
    root = Tk()
    root.title(title)
    i = 0
    args = {}
    for key, variable in kwargs.items():
        var = {}
        key_txt = key
        Label(text=variable["label"]).grid(row=i)
        key = Entry()
        key.grid(row=i, column=1)
        var["value"] = key
        var["type"] = variable["type"]
        var["default"] = variable["default"]
        kwargs[key_txt] = var
        i += 1
    message_button = Button(text="Рассчитать", command=lambda: calculate(**kwargs))
    message_button.grid(row=(i + 1), column=2, padx=5, pady=5, sticky="e")
    root.mainloop()
gui_title = "Лабораторная работа № 6. ТМО."
gui_var_lmbd = {"label": "Интенсивность поломки станков (в ед. вр.):", "type": float, "default": 0.5}
gui_var_mu = {"label": "Интенсивность починки станков (в ед. вр.):", "type": float, "default": 2.5}
gui_vars = {"lmbd": gui_var_lmbd, "mu": gui_var_mu}
make_gui(gui_title, **gui_vars)

Затык в момент объявления переменных через locals(). Вроде все перечитал не могу понять в чем проблема. Возникает ошибка:

NameError: name ‘mu’ is not defined

Однако print(locals()) говорит, что она есть:

{'mu': 2.5, ‘key’: ‘lmbd’, ‘kwargs’: {'mu': {'type': <class ‘float’>, ‘default’: 2.5, ‘value’: <tkinter.Entry object .140529577587040>}, ‘lmbd’: {'type': <class ‘float’>, ‘default’: 0.5, ‘value’: <tkinter.Entry object .140529576789496>}}, ‘lmbd’: 0.5, ‘value’: {'type': <class ‘float’>, ‘default’: 0.5, ‘value’: <tkinter.Entry object .140529576789496>}}

Скажите что я делаю не так ну и заодно жду критики самой идей, стиля кода и т.д.

Отредактировано winmasta (Ноя. 19, 2017 18:34:06)

Офлайн

#2 Ноя. 19, 2017 17:51:49

Romissevd
От: Счастье
Зарегистрирован: 2015-03-01
Сообщения: 533
Репутация: +  76  -
Профиль   Отправить e-mail  

Как создать переменную из словаря с именем ключа ?

 print(locals()['mu'])

Офлайн

#3 Ноя. 19, 2017 18:30:53

winmasta
Зарегистрирован: 2017-10-03
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Как создать переменную из словаря с именем ключа ?

Romissevd
А можно как-то сделать так, чтобы обращаться к переменным напрямую как обычно ?

Офлайн

#4 Ноя. 19, 2017 19:52:15

PEHDOM
Зарегистрирован: 2016-11-28
Сообщения: 2196
Репутация: +  294  -
Профиль   Отправить e-mail  

Как создать переменную из словаря с именем ключа ?

winmasta
Задавал тут вопрос про tkinter и как конструировать окна с произвольными полями ввода, но тему найти не могу, видимо удалена.
WTF? http://python.su/forum/topic/34089/
Если посмотреть профиль то там есть пункт посмотреть все сообщения..

     for key, value in kwargs.items():
        try:
            locals()[key] = value["type"](value["value"].get())
        except ValueError:
            locals()[key] = value["type"](value["default"])
ересь полнейшая, из локалс можно получить данные , но не изменить таким путем, для этого есть обьективные причины.
http://rupython.com/globals-locals-vars-1141.html



==============================
Помещайте код в теги:
[code python][/code]
Бериегите свое и чужое время.

Отредактировано PEHDOM (Ноя. 19, 2017 20:09:00)

Офлайн

#5 Ноя. 19, 2017 20:00:40

marvellik
Зарегистрирован: 2016-05-15
Сообщения: 639
Репутация: +  73  -
Профиль   Отправить e-mail  

Как создать переменную из словаря с именем ключа ?

чтобы обращаться к ним как обычно их надо инициализировать а для этого нужно знать сколько будет полей ввода. я так понимаю вам нужно извлечь данные из окон ввода и что то с ними сделать? примерно так

 from tkinter import *
def calculate(var):
    for i,key in var.items():
        print(key.get())
def make_gui(var):
    for i,variable in enumerate(gui_var_lmbd):
        Label(text=variable).grid(row=i)
        var[i] = Entry()
        var[i].grid(row=i, column=1)
    message_button = Button(text="Рассчитать", command=lambda: calculate(var))
    message_button.grid(row=(i + 1), column=2, padx=5, pady=5, sticky="e")
              
var = {}   
root = Tk()
root.title("Лабораторная работа № 6. ТМО.")
gui_var_lmbd = ["Интенсивность поломки станков (в ед. вр.):",
 "Интенсивность починки станков (в ед. вр.):"]
make_gui(var)
root.mainloop()

Отредактировано marvellik (Ноя. 19, 2017 20:01:18)

Офлайн

#6 Ноя. 19, 2017 20:31:32

PEHDOM
Зарегистрирован: 2016-11-28
Сообщения: 2196
Репутация: +  294  -
Профиль   Отправить e-mail  

Как создать переменную из словаря с именем ключа ?

winmasta
Скажите что я делаю не так ну и заодно жду критики самой идей, стиля кода и т.д.
забить на процедурный подход, с классами оно решаеться намного проще, тем более что тогда можно создавать окно не одной строчкой а несколькими.
Переделал немного промиер из “потеряного” топика:
 from tkinter import *
class MyWindow:
    def __init__(self, title):
        self.title = title
        self.values = []
        self.names = []
        self.entries = {}
    def set_names(self, *args):
        self.names = args
    def set_values(self, *args):
        self.values = args
    def exec(self):
        root = Tk()
        root.title(self.title)
        for i, key in enumerate(self.names):
            label = Label(root, text = '{}: '.format(key))
            entry = Entry(root)
            entry.insert(END, self.values[i])
            label.grid(row= i, column=0)
            entry.grid(row= i, column=1)
            self.entries[key] = entry
        btn = Button(root,text="Print Fiedls")
        btn.grid(row= i+1, column=1)
        btn.bind('<Button-1>', self.ret)
        root.mainloop()
    def ret(self, event):
        for key, entry in self.entries.items():
            print(key, entry.get() )
if __name__ == '__main__':
    win = MyWindow('Окошко, епта!!')
    win.set_names('адын', 'джва', 'тры')
    win.set_values('первыйнах','второйнах','15')
    win.exec()
    win = MyWindow('Second WIND')
    win.set_names('первый', 'второй', 'третий', 'четвертый', 'последний')
    win.set_values(12, 33, False, 34.4 , 111)
    win.exec()



==============================
Помещайте код в теги:
[code python][/code]
Бериегите свое и чужое время.

Отредактировано PEHDOM (Ноя. 19, 2017 20:35:21)

Офлайн

#7 Ноя. 20, 2017 04:08:40

winmasta
Зарегистрирован: 2017-10-03
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Как создать переменную из словаря с именем ключа ?

marvellik
чтобы обращаться к ним как обычно их надо инициализировать а для этого нужно знать сколько будет полей ввода. я так понимаю вам нужно извлечь данные из окон ввода и что то с ними сделать? примерно так
Вот проблема в том, что хочется построить конструктор для любого количества полей ввода, чтобы использовать один и тот же в разных файлах (лабах)

Офлайн

#8 Ноя. 20, 2017 04:12:01

winmasta
Зарегистрирован: 2017-10-03
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Как создать переменную из словаря с именем ключа ?

PEHDOM
from tkinter import *
class MyWindow:
def __init__(self, title):
self.title = title
self.values =
self.names =
self.entries = {}
def set_names(self, *args):
self.names = args
def set_values(self, *args):
self.values = args
def exec(self):
root = Tk()
root.title(self.title)
for i, key in enumerate(self.names):
label = Label(root, text = ‘{}: ’.format(key))
entry = Entry(root)
entry.insert(END, self.values)
label.grid(row= i, column=0)
entry.grid(row= i, column=1)
self.entries = entry
btn = Button(root,text=“Print Fiedls”)
btn.grid(row= i+1, column=1)
btn.bind('<Button-1>', self.ret)
root.mainloop()
def ret(self, event):
for key, entry in self.entries.items():
print(key, entry.get() )
if __name__ == ‘__main__’:
win = MyWindow('Окошко, епта!!')
win.set_names('адын', ‘джва’, ‘тры’)
win.set_values('первыйнах','второйнах','15')
win.exec()
win = MyWindow('Second WIND')
win.set_names('первый', ‘второй’, ‘третий’, ‘четвертый’, ‘последний’)
win.set_values(12, 33, False, 34.4 , 111)
win.exec()

Спасибо большое, видимо то, что нужно. Я чувствую что пора переходить к ООП но вот никак не могу сообразить, разберу Ваш код внимательно.

Офлайн

#9 Ноя. 21, 2017 12:14:36

winmasta
Зарегистрирован: 2017-10-03
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

Как создать переменную из словаря с именем ключа ?

Разобрался с классом, чуть перепилил под себя. Основной вопрос остался: как можно обозначить имена переменных, передать их в объект класса, затем по нажатию кнопки вызывается отдельная функция расчетов и там уже нужно назначить имена переменных и их значения, которые мы передали объекту класса. Т.е. нужно передать имена и значения переменных в функцию и там проводить расчеты. Извините если плохо сформулировал.

Офлайн

#10 Ноя. 21, 2017 13:51:27

PEHDOM
Зарегистрирован: 2016-11-28
Сообщения: 2196
Репутация: +  294  -
Профиль   Отправить e-mail  

Как создать переменную из словаря с именем ключа ?

winmasta
Извините если плохо сформулировал.
очень плохо, я вообще ничерта не понял… хотя интуитивно могу предположить что нужно по нажатию кнопки вызывать некую функцию которая будет проводить определенные вычисления беря данные из введенных в ентри значений?
Тут вариантов на самом деле масса, можно гонять словари, можно передавать ссылки на окно или список полей ввода, можно даже написать небольшую реализацию сигналов а-ля pyQT типа такого https://stackoverflow.com/questions/21101500/custom-pyqtsignal-implementation, можно написать свой класс в котором будет содержаться все данные: , заголовки, поля, значения, типы передаваемых и возвращаемых значений местоположение элементов на форме…, и уже экземпляры этих классов передвать классу окна или функции рассчета.
Но ИМХО наиболее универсальный и простой способ это калбек функция. Заголовки и значения мы передаем списокм, и возвращаем мы тоже список в том же порядке в каком передавали заголовки:
 from tkinter import *
class MyWindow:
    def __init__(self, title):
        self.title = title
        self.values = []
        self.names = []
        self.entries = []
    def set_names(self, *args):
        self.names = args
    def set_values(self, *args):
        self.values = args
    def set_callback(self, callback_func):
        self.callback_func = callback_func
    def exec(self):
        root = Tk()
        root.title(self.title)
        for i, key in enumerate(self.names):
            label = Label(root, text = '{}: '.format(key))
            entry = Entry(root)
            entry.insert(END, self.values[i])
            label.grid(row= i, column=0)
            entry.grid(row= i, column=1)
            self.entries.append(entry)
        self.btn = Button(root,text="Print Fiedls")
        self.btn.grid(row= i+1, column=1)
        self.btn.bind('<Button-1>', self.ret)
        root.mainloop()
    def ret(self, event):
        result = [entry.get() for entry in self.entries]
        try:
            self.callback_func(*result)
        except AttributeError:
            print('callback function is not set')
def rect_sqare(height, width):
    print('Площадь прямоугольника высотой: {}, шириной: {} ='.format(height, width), int(height) * int(width))
def prll_space(height, width, depth):
    print('Обьем параллелепипеда высотой: {}, шириной:{}, глубиной: {}  ='.format(height, width, depth), int(height) * int(width)* int(depth))
if __name__ == '__main__':
    win = MyWindow( 'Площать прямоугольника')
    win.set_names('высота', 'ширина' )
    win.set_values(1, 2)
    win.set_callback(rect_sqare)
    win.exec()
    win = MyWindow('Обьем паралелепипеда')
    win.set_names('высота', 'ширина', 'глубина')
    win.set_values(1, 2, 3)
    win.set_callback(prll_space)
    win.exec()
>>> 
Площадь прямоугольника высотой: 1, шириной: 2 = 2
Площадь прямоугольника высотой: 3, шириной: 2 = 6
Обьем параллелепипеда высотой: 1, шириной:2, глубиной: 3  = 6
Обьем параллелепипеда высотой: 3, шириной:2, глубиной: 3  = 18
>>> 
хотя если у вас планируеться “сложные” окна, то можно смотреть в сторону классов, по принипу у вас отдельный класс где храниться вся инфа про ти что за виджет, какое у него описание, какой тип и значение он хранит и тд… И уже экземпляры этих классов гонять.



==============================
Помещайте код в теги:
[code python][/code]
Бериегите свое и чужое время.

Отредактировано PEHDOM (Ноя. 21, 2017 14:08:04)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version