0

So basicly I'm trying to call functions within classes using strings. So normally if you create a class, you're able to call the functions as seen below:

class Example:

    def __init__(self, name, address):
        self.name = name
        self.address = address

    def test1(self):
        print(self.name)

    def test2(self):
        print(self.address)


exm = Example("exm", 0x00)
exm.test1()
exm.test2()

This works fine ofcourse but I'm working on a bigger code using a lot of strings and I'm trying to call a function within a class using my strings. Say you have a variable with the string "test1" and then try to call the function as seen below:

input_user = "test1"
exm.input_user()

This doesn't work because Python doesn't recognize it as an attribute of the class. If I use a normal function that's not within a class, I would be able to call it using a string with the globals() function.

def test1():
    print("Succes!")


func = "test1"
call = globals()[func]
call()

But if I try to use the same method to call my function within a class then I get a KeyError. Using the code below:

input_user = "exm.test1"
call = globals()[input_user]
call()

Does anyone have a solution for this? Any help would be greatly appreciated. Thank you in advance!

DGBMenno
  • 77
  • 9
  • 1
    Why does your user input include variable names? – chepner Mar 30 '20 at 13:18
  • @chepner Because in my real code I have a lot of classes and objects that are intertwined. I want to create a function where you can put in a string and that it scans through all the different classes and gives back te names of all the matching objects and attributes. The question I asked was the first problem I found while trying to create this function – DGBMenno Mar 30 '20 at 14:01
  • What's wrong with `(exm, "test1")` instead of `"exm.test1"`? The only entities who would need to communicate with your code via plain strings are those entities who shouldn't be aware of a variable named `exm` in the first place. – chepner Mar 30 '20 at 14:03
  • Well this was just a small example of what I'm trying to do. When I'm scanning through attributes of my objects it retuns strings. So then I want to combine all the strings to create a path to the right object. So for example if I want path 'obj1.obj2.obj3.obj4', I'll get all those obj values in strings. So I'm trying to figure out a way to combine the strings and make them call a function – DGBMenno Mar 30 '20 at 14:13
  • 1
    My short answer is, don't use strings like that. What problem are you actually trying to solve that you think this is the solution? – chepner Mar 30 '20 at 14:15
  • I have a class to create objects that are called "fields", those objects are defined inside another classses __init__ that's called "map". Those maps are then defined inside of other maps and this can go on forever. Each field has it's own name so I'm trying to make a function that can scan through all the maps and fields and return the path to the field with the name that is defined by the user. Does this sort of make sense? – DGBMenno Mar 30 '20 at 14:22

1 Answers1

3

Use getattr.

input_user = "test1"
getattr(exm, input_user)()

Or, use operator.methodcaller.

from operator import methodcaller

methodcaller(input_user)(exm)
chepner
  • 497,756
  • 71
  • 530
  • 681
  • try storing the class objects in a dictionary for more dynamic approach on this `class_dictionary = { 'exm': Example("from function", '0x00') } user_input = "exm.test1" input_user_list = user_input.split(".") classname, function_name = input_user_list[0], input_user_list[1] func = getattr(class_dictionary["exm"], function_name) func()` – Kiran Gali Mar 30 '20 at 13:13
  • @chepner But this way I can only put the attribute as a string but not the actual object. Or am I looking at this wrong? – DGBMenno Mar 30 '20 at 14:06
  • 1
    I overlooked the end of your question when I posted this, but i question why you unparsed strings like that in the first place. – chepner Mar 30 '20 at 14:14