0

My requirement is to use variable value for referncing class/dictionaries in Python. As a sample example, I have following data :-

class test1:
    pass

class test2:
   pass

test1_dict = {}
test2_dict = {}

testvariable = "test1"

Now I want to check value of testvariable and create an instance of class and append it in dictionary.

e.g.

if testvariable == "test1":
    test1inst = test1()
    test1_dict["test1"] = test1inst
elif testvariable == "test2":
    test2inst = test2()
    test2_dict["test2"] = test2inst

In the above code, I have to explicitly use if/else to check the value of testvariable and do the operations accordingly.

In my real scenario, I could have multiple values of testvariable and there could be multiple places where if/else check would be required. So, is it possible that somehow, I could be able to use the value of testvariable directly to refer dictionary/class instances without using if/else.

sarbjit
  • 3,786
  • 9
  • 38
  • 60

3 Answers3

10

There is almost never a good reason to look up names like this. Python has a perfectly good data structure for mapping names to objects, and that is a dict. If you ever find yourself saying "I need a dynamic lookup of something", then a dict is the answer. In your case:

from collections import defaultdict
test_classes = {
    'test1': test1,
    'test2': test2
}
test_instances = defaultdict(list)
test_instances[testvariable].append(test_classes[testvariable])
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • I agree with you, but I am facing problems implementing the same in my actual code. Please see my edit, which represents my actual problem more closely. – sarbjit Aug 23 '13 at 10:39
0

I agree with Daniel Roseman that there is almost never a good reason to do this. However, I'm up for a challenge! The OP follows my lead at his or her own peril.

The secret is to use Python's exec function, which permits executing the contents of a string as Python code:

So,

if testvariable == "test1":
    test1inst = test1()
    test1_dict["test1"] = test1inst
elif testvariable == "test2":
    test2inst = test2()
    test2_dict["test2"] = test2inst

becomes

exec("%sinst = %s()" % (testvariable, testvariable))
exec("%s_dict[testvariable] = %sinst" % (testvariable, testvariable))

albeit with the caveat that other values of testvariable do nothing in the OP's case, and in the case using exec() result in NameError exceptions.

Mark R. Wilkins
  • 1,282
  • 7
  • 15
  • No, bad idea. You can do the same by looking up the class in the local variables or global variables: inst = locals()[testvariable] – djhoese Aug 23 '13 at 13:33
  • Very true, although this method doesn't require testing for from where in the scope it comes. Also, I think my answer made clear that it was a bad idea to do this. :) – Mark R. Wilkins Aug 23 '13 at 15:30
  • 1
    Yeah, I just saw "exec" and went to a very dark place. :) – djhoese Aug 23 '13 at 15:36
0

I'm going to combine some other posts and say that Python already has a dictionary that maps names of objects to the object. You can access local and global variables so as long as your class is defined in the module you can do:

my_inst[testvariable] = locals()[testvariable]()
djhoese
  • 3,567
  • 1
  • 27
  • 45