[Tutor] Dynamic Function Calls

Dave Angel davea at ieee.org
Fri Aug 14 23:06:02 CEST 2009


Megan Land wrote:
> <snip>
> I tried what you said.  I can call the function by itself (not within the
> dictionary).  I also printed the help(__name__).  All of my functions were
> listed.  Here's a more representative example of my code (I doing this for
> work so I don't want to give my entire program away):
>
> import os
> class Test():
>     def func(self):
>         funcDict={".txt":text, ".html":html}
>         exList=os.listdir("/home/megan/test")
>         for i in exList:
>           (filePath, fileName)=os.path.split(i)
>           (name, extension)=os.path.splitext(fileName)
>           self.funcDict[extension]()
>
>     def text(self):
>         print "This is a text file"
>
>     def html(self):
>         print "This is an html file"
>
> def main():
>     newTest=Test()
>     newTest.func()
>
>
> if __name__=="__main__":
>     main()
>
>
> Traceback (most recent call last):
>   File "test.py", line 23, in <module>
>     main()
>   File "test.py", line 19, in main
>     newTest.func()
>   File "test.py", line 4, in func
>     funcDict={".txt":text, ".html":html}
> NameError: global name 'text' is not defined
>
> It worked fine until I put it inside of a class, but I'm not sure what that
> would have to do with it.  I don't need to have use all that, but now that
> everything is setup like that I want to keep it that way.  Any help you can
> provide will be greatly appreciated.
>
> Megan Land
>   

As you said, it worked fine till you put those two function definitions 
inside a class.  As I guessed earlier, your use of the word "method" was 
a tipoff.  Anyway, within the method func(), an unqualified name will be 
searched for locally (an attribute of func()), then globally (within the 
module, at global scope).  It does not search for other methods.

Still, the first question I have to ask is "why are text() and html() 
instance methods?"   You're not using self anywhere in those methods, 
but maybe you are in your actual code. 

I have to assume something, so I'll assume you need self for all three 
methods.  In this case, simply change the line to:
      funcDict={".txt":self.text, ".html":self.html}

and it should work fine.  You're creating bound methods, which already 
know their self-value when they're placed in the funcDict.

If I assume they don't need self, I'd just move them to global scope, 
and forget about it.   But if you just can't do that, then how about 
nested functions?  (I had already added the parameter "name" for testing 
purposes, so please forgive that change below.)

    def func(self):
        def text(name):
            print "This", name, "is also a text file, nested"
        def html(name):
            print "This", name, "is also an html file, nested"
        funcDict={".txt":self.text, ".html":self.html}
        exList=os.listdir(".")
        for i in exList:
          (filePath, fileName)=os.path.split(i)
          (name, extension)=os.path.splitext(fileName)
          if extension in funcDict:
              funcDict[extension](name)

I believe you could also do something with the @static decorator, but I 
haven't played with it, and it doesn't look like you need it anyway.

DaveA




More information about the Tutor mailing list