0

I have created a namedtuple like this.

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)

I can access values easily like this.

Point_2.x

But when I try to get Point_2 from an entry box I get this error.

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

So I learned that entry boxes return string values.

How can I get a namedtuple value from a string?

String_1 = "Point_2"
String_1 ???

Thanks.

Sorry for the confusion. Hope this is more clear.

So here I decided to add Point_1.x with Point_2.x and add the total to my Dialog as a label.

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()

Now I want to do the same thing but have a user decide which point to add.

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 problem is that My_Entry_1.get() and My_Entry_2.get() are strings. And I get the error AttributeError: 'str' object has no attribute 'x'.

So my question was how can I take the string from My_Entry_1 and My_Entry_2 to access the x values?

Sorry again for the confusion.

Thanks.

GrandJoss
  • 27
  • 1
  • 7

2 Answers2

2

I'm not sure what entry box is in this context, but I think you have a few choices here.

1) Enter these points into a dictionary and indexing it via the string that you get back from the entry box.

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) If these are on a module level, you can try grabbing the variables from the module context.

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

3) If you're trying to reference it from within a function, you could try eval: https://docs.python.org/3/library/functions.html#eval or, even better 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
  • I'd switch #3 to use the `locals()` `dict` over `eval` since you have an exact name. Avoids the security risks of `eval`. Also, there is no need for `globals` in #2, you an just use `sys.modules[__name__]` directly, no quotes around `__name__`, since `__name__` always exists for modules (unless you've shadowed it locally for god knows what reason). – ShadowRanger Feb 19 '16 at 20:55
  • Sorry. This is what I mean. My_Entry = Entry(Dialog, width=10).pack() – GrandJoss Feb 19 '16 at 20:58
  • 1
    @GrandJoss: Something like #1 is almost certainly what you want to try to do. – Gerrat Feb 19 '16 at 21:04
  • Thanks @ShadowRanger I've updated my answer to instead use locals() for #3. – Ryan La Forge Feb 19 '16 at 21:19
0

You generally wouldn't do this (it is unsafe with arbitrary input), but you could use eval:

String_1 = eval("Point_2")

Now, String_1 points to your already-existing variable Point_2.

Ben Soyka
  • 816
  • 10
  • 25
Gerrat
  • 28,863
  • 9
  • 73
  • 101
  • This works fine. I can use String_1.x to get the x value of Point_2 that came from an entry box. But you are scaring me with this method being unsafe. I am a newbie to coding and I don't want to mess up my code. If my namedtuple is fixed and will never change am I good to go with this method? – GrandJoss Feb 19 '16 at 20:54
  • @GrandJoss: `eval` can execute arbitrary Python code, not just look up variables, that's why it's frowned on. Using the `dict` returned by `globals()`, `locals()` or `vars()` (depending on where the names exist) means the worst they can do is get you to read an existing variable or raise `KeyError`), where `eval` lets them, say, delete all files in your working directory by entering `[__import__('os').unlink(x) for x in __import__('os').listdir('.')]` instead of `Point_2`. – ShadowRanger Feb 19 '16 at 20:58
  • @GrandJoss: As @ShadowRanger mentioned, this is likely **not** what you want if you don't really know what you are doing. The `locals()` is a little better, but I think you may want to rethink your design. I doubt you need to do any of these to do what you want. Maybe elaborate your question to let us know why you're trying to do this. – Gerrat Feb 19 '16 at 21:02