получение значения namedtuple из строки

Я создал namedtuple, подобный этому.

Named_Tuple_1 = namedtuple("Coordinates", ["x", "y", "z"], verbose=False, rename=False)

Point_1 = Named_Tuple_1(x=1, y=1, z=1)
Point_2 = Named_Tuple_1(x=2, y=2, z=2)
Point_3 = Named_Tuple_1(x=3, y=3, z=3)

Я могу легко получить доступ к таким значениям.

Point_2.x

Но когда я пытаюсь получить Point_2 из поля ввода, я получаю эту ошибку.

AttributeError: 'str' object has no attribute 'x'

Итак, я узнал, что поля ввода возвращают строковые значения.

Как я могу получить значение namedtuple из строки?

String_1 = "Point_2"
String_1 ???

Спасибо.

Извините за путаницу. Надеюсь, это более понятно.

Итак, здесь я решил добавить Point_1.x с Point_2.x и добавить итог в свой диалог в качестве метки.

Named_Tuple_1 = namedtuple("Coordinates", ["x", "y", "z"], verbose=False, rename=False)
Point_1 = Named_Tuple_1(x=1, y=2, z=3)
Point_2 = Named_Tuple_1(x=4, y=5, z=6)
Point_3 = Named_Tuple_1(x=7, y=8, z=9)

def ADD_x_1():
    Sum_of_x = Point_1.x + Point_2.x
    My_Label_1 = Label(Dialog, text=Sum_of_x)
    My_Label_1.pack()

Dialog = Tk()
My_Button_1 = Button(Dialog, text="Add x Value", command=ADD_x_1)
My_Button_1.pack()
Dialog.mainloop()

Теперь я хочу сделать то же самое, но чтобы пользователь сам решал, какую точку добавить.

def ADD_x_2():
    First_Point_x = My_Entry_1.get().x
    Second_Point_x = My_Entry_2.get().x
    Sum_of_x = First_Point_x + Second_Point_x
    My_Label_3 = Label(Dialog, text=Sum_of_x)
    My_Label_3.pack()

Dialog = Tk()
My_Label_1 = Label(Dialog, text="Select first point")
My_Label_1.pack()
My_Entry_1 = Entry(Dialog, bd=2, width=10)
My_Entry_1.pack()
My_Label_2 = Label(Dialog, text="Select second point")
My_Label_2.pack()
My_Entry_2 = Entry(Dialog, bd=2, width=10)
My_Entry_2.pack()
My_Button_2 = Button(Dialog, text="Add x Value", command=ADD_x_2)
My_Button_2.pack()
Dialog.mainloop()

Моя проблема в том, что My_Entry_1.get() и My_Entry_2.get() являются строками. И я получаю сообщение об ошибке AttributeError: объект 'str' не имеет атрибута 'x'.

Итак, мой вопрос заключался в том, как я могу взять строку из My_Entry_1 и My_Entry_2 для доступа к значениям x?

Еще раз извините за путаницу.

Спасибо.


person GrandJoss    schedule 19.02.2016    source источник


Ответы (2)


Я не уверен, что такое поле ввода в этом контексте, но я думаю, что у вас есть несколько вариантов.

1) Введите эти точки в словарь и проиндексируйте его через строку, которую вы получите обратно из поля ввода.

point_dict = {'Point_1': Point_1, 'Point_2': Point_2, 'Point_3': Point_3}
entry_point = {{however you got the string from the entrypoint}}
point = point_dict[entry_point]
point.x

2) Если они находятся на уровне модуля, вы можете попробовать получить переменные из контекста модуля.

import sys
modname = globals()['__name__']
modobj  = sys.modules[modname]
point = getattr(modobj, 'Point_1')

3) Если вы пытаетесь сослаться на него из функции, вы можете попробовать eval: https://docs.python.org/3/library/functions.html#eval или, что еще лучше, locals(): https://docs.python.org/2/library/functions.html#locals

##Point_1 = eval('Point_1') risk due to executing arbitrary code
Point_1 = locals()['Point_1']  # Use this instead
person Ryan La Forge    schedule 19.02.2016
comment
Я бы заменил #3 на locals() dict вместо eval, так как у вас есть точное имя. Избегает рисков безопасности eval. Кроме того, нет необходимости в globals в #2, вы просто используете sys.modules[__name__] напрямую, без кавычек вокруг __name__, так как __name__ всегда существует для модулей (если только вы не затенили его локально бог знает по какой причине). - person ShadowRanger; 19.02.2016
comment
Извиняюсь. Это то, что я имею в виду. My_Entry = Запись(Диалог, ширина=10).pack() - person GrandJoss; 19.02.2016
comment
@GrandJoss: Что-то вроде № 1 — это почти наверняка то, что вы хотите попробовать сделать. - person Gerrat; 20.02.2016
comment
Спасибо @ShadowRanger. Я обновил свой ответ, чтобы вместо этого использовать locals() для # 3. - person Ryan La Forge; 20.02.2016

Обычно вы этого не делаете (это unsafe с произвольным вводом), но вы можете использовать оценка:

String_1 = eval('Point_2")

Теперь он указывает на вашу уже существующую переменную Point_2.

person Gerrat    schedule 19.02.2016
comment
Это прекрасно работает. Я могу использовать String_1.x, чтобы получить значение x Point_2, полученное из поля ввода. Но вы пугаете меня тем, что этот метод небезопасен. Я новичок в кодировании, и я не хочу испортить свой код. Если мой namedtuple исправлен и никогда не изменится, могу ли я использовать этот метод? - person GrandJoss; 19.02.2016
comment
@GrandJoss: eval может выполнять произвольный код Python, а не просто искать переменные, поэтому его не одобряют. Использование dict, возвращаемого globals(), locals() или vars() (в зависимости от того, где существуют имена), означает, что худшее, что они могут сделать, это заставить вас прочитать существующую переменную или поднять KeyError), где eval позволяет им, скажем, удалить все файлы в вашей рабочей памяти. директории, введя [__import__('os').unlink(x) for x in __import__('os').listdir('.')] вместо Point_2. - person ShadowRanger; 19.02.2016
comment
@GrandJoss: Как упомянул @ShadowRanger, это, вероятно, не то, что вам нужно, если вы действительно не знаете, что делаете. locals() немного лучше, но я думаю, вы захотите переосмыслить свой дизайн. Я сомневаюсь, что вам нужно делать что-то из этого, чтобы делать то, что вы хотите. Возможно, уточните свой вопрос, чтобы сообщить нам, почему вы пытаетесь это сделать. - person Gerrat; 20.02.2016