1

I am generating variables through a list and a class. All that works fine. outside a function i can call the data one of these variables hold, but inside a function i can call the data directly, but not using the vars()[] method

I have tried to search for a direct answer on google and this site, but i have been unable to find a solution.

what can i do to make the:

print(str(k)+" :"+str(vars()[k].data))

inside runner() work?

class LED:
    def __init__(self, gpio):
        self.gpio = gpio
        self.data = []
        self.state = False


LED_list = {'G1':8}

for k,v in LED_list.items():
    vars()[k] = LED(v)

G1.data = [10,15,20,25]

print("outside")
for k,v in LED_list.items():
    print(str(k)+" :"+str(vars()[k].data))

def runner():
    print("inside")
    for k,v in LED_list.items():
        print(k,v)
        print("G1 data: "+str(G1.data))
        print(str(k)+" :"+str(vars()[k].data))

runner()

This is my output:

outside
G1 :[10, 15, 20, 25]
inside
G1 8
G1 data: [10, 15, 20, 25]
Traceback (most recent call last):
  File "/.../Main2.py", line 23, in <module>
    runner()
  File "/.../Main2.py", line 21, in runner
    print(str(k)+" :"+str(vars()[k].data))
KeyError: 'G1'
  • 7
    It *is* working. Inside a function, `vars()` is equivalent to `locals()`, (note, modifications to the dict returned by `locals()` do not get reflected in the actual local namespace) What you are tryin to do in the first place is highly inadvisable, don't use *dynamic variables*, just use a *container*, like a `dict`, which is essentially what you have to end up doing anyway if you want to use dynamic variables. – juanpa.arrivillaga Aug 27 '19 at 20:21
  • @juanpa.arrivillaga thank you for your reply. I did come across the locals() part. But i am not an especially good programmer, so i don't know exactly what you mean. Neither do i understand the part with a container (sry). I just dont get why i cant do the same call in a function as outside. –  Aug 27 '19 at 20:30
  • @Hudlommen2 That's exactly why you shouldn't be trying to do this. See [How do I create a variable number of variables?](https://stackoverflow.com/questions/1373164/how-do-i-create-a-variable-number-of-variables) for a discussion of better alternatives. – glibdud Aug 27 '19 at 20:34
  • @glibdud Ok. But just as a last thing? is using dict as container faster, or? why is this a better solution? –  Aug 27 '19 at 20:40
  • @Hudlommen2 It keeps you from having to do exactly this sort of hacky stuff with `vars()` etc. It keeps your code simpler, more readable, and more maintainable. – glibdud Aug 27 '19 at 20:43
  • @Hudlommen2 because it is idiomatic and organized. The performance is essentially equivalent. Note, your attempt with `vars` **already uses a `dict`**, that is, `vars()` returns a `dict`. – juanpa.arrivillaga Aug 27 '19 at 20:44
  • @glibdud - Ill look into all that as my next project. using globals() instead of vars() worked. I don't understand why. Magic.. but apparently bad magic –  Aug 27 '19 at 20:49

1 Answers1

1

globals() works instead of vars() - but read the notes under, because it is not the correct solution to the problem to use vars() and globals().


class LED:
    def __init__(self, gpio):
        self.gpio = gpio
        self.data = []
        self.state = False


LED_list = {'G1':8}

for k,v in LED_list.items():
    vars()[k] = LED(v)

G1.data = [10,15,20,25]

print("outside")
for k,v in LED_list.items():
    print(str(k)+" :"+str(vars()[k].data))

def runner():
    print("inside")
    for k,v in LED_list.items():
        print(k,v)
        print("G1 data: "+str(G1.data))
        print(str(k)+" :"+str(globals()[k].data))

runner()
Dan D.
  • 73,243
  • 15
  • 104
  • 123