Passing a function name as an argument in a function
I am trying to pass the name of a function into another function as an argument but I get an error: TypeError: 'str' object is not callable
. Here is a simplified example of the problem:
def doIt(a, func, y, z):
result = z
result = func(a, y, result)
return result
def dork1(arg1, arg2, arg3):
thing = (arg1 + arg2) / arg3
return thing
def dork2(arg1, arg2, arg3):
thing = arg1 + (arg2 / arg3)
return thing
When I call doIt like so:
var = 'dork1'
ned = doIt(3, var, 4, 9)
print (ned)
I get:
Traceback (most recent call last):
File "<pyshell#9>", line 1, in <module>
ned = doIt(3, var, 4, 9)
File "<pyshell#2>", line 3, in doIt
result = func(a, y, result)
TypeError: 'str' object is not callable
If you want to pass the function's name, as you said and you're doing, of course you can't call it -- why would one "call a name"? It's meaningless.
If you want to call it, pass the function itself, that is, most emphatically not
var = 'dork1'
but rather
var = dork1
without quotes!
Edit: the OP wonders in a comment (!) how to get a function object given the function name (as a string). As it happens I just showed how to do that in a tutorial I taught at OSCON (from which I'm just back) -- get the slides from here and see page 47, "Lazy-loading callbacks":
class LazyCallable(object):
def __init__(self, name):
self.n, self.f = name, None
def __call__(self, *a, **k):
if self.f is None:
modn, funcn = self.n.rsplit('.', 1)
if modn not in sys.modules:
__import__(modn)
self.f = getattr(sys.modules[modn],
funcn)
self.f(*a, **k)
So you could pass LazyCallable('somemodule.dork1')
and live happily ever after. If you don't need to deal with the module of course (what a weird architecture that must imply!-) it's easy to adjust this code.
Don't pass the name of a function.
Pass the function.
fun = dork1
ned = doIt(3, fun, 4, 9)
print (ned)
I was thrilled to find this and I don't know if this was answered. My solution to this is as follows:
def doIt(func, *args):
func_dict = {'dork1':dork1,'dork2':dork2}
result = func_dict.get(func)(*args)
return result
def dork1(var1, var2, var3):
thing = (float(var1 + var2) / var3)
return thing
def dork2(var1, var2, var3):
thing = float(var1) + (float(var2) / var3)
return thing
This can be run as follows:
func = 'dork2'
ned = doIt(func,3, 4, 9)
print ned
var = 'dork1'
ned = doIt(3, var, 4, 9)
print (ned)
In this example, var
is a string. The doIt
function "calls" its second argument (for which you pass var
). Pass a function instead.