dynamic construction of variables / function names

Steven D'Aprano steve at REMOVEMEcyber.com.au
Thu Mar 30 10:24:10 CEST 2006


Sakcee wrote:

> python provides a great way of dynamically creating fuctions calls and
> class names from string
> 
> a function/class name can be stored as string and called/initilzed
> 
> e.g
> 
> def foo(a,b):
>     return a+b
> 
> def blah(c,d):
>     return c*d
> 
> 
> list = ["foo", "blah"]
> 
> for func in list:
> 	print func(2,4)
> 
> or similar items

Have you actually tried to do this? It doesn't work:

Traceback (most recent call last):
   File "<stdin>", line 2, in ?
TypeError: object of type 'string' is not callable

(Also, it is poor practice to shadow the built-in list 
as you have.)

You are attempting to call "foo"(2, 4). Strings are not 
callable.

Two ways to actually do what you are trying to do is 
with eval and exec:

 >>> eval("foo(2, 3)")
5
 >>> exec("print foo(2, 3)")
5

but be aware of the possible security implications of 
eval and exec.

If you are calling instance methods, you can use getattr:

 >>> class Foo:
...     def foo(self, x,y):
...             return x+y
...
 >>> getattr(Foo(), "foo")(2, 3)
5

But the best way is, if possible, avoid this altogether 
and remember that functions are first-class objects in 
Python. Instead of doing this:

L = ["foo", "bar"]
for func in L:
     print eval(func + "(2, 3)")

do this:

L = [foo, bar]  # list containing function objects
for func in L:
     print func(2, 3)


> what is the way if the names of functions are some modification e.g

As far as I know, the only ways are: use eval or exec, 
or look in locals and/or globals:

 >>> func = locals().get("f" + "oo", None)
 >>> if callable(func):
...     func(2, 3)
...
5

You can use globals() instead of locals(), but there 
may be issues with scoping rules that I can't think of.

Personally, I think the best way is: find another way 
to solve your problem.


> is it correct way, is there a simple way, is this techniqe has a name?

I'm told that some people call this "dynamic 
programming", but personally I call it "difficult to 
maintain, difficult to debug programming".

(Before people get all cranky at me, I'm aware that it 
isn't *always* the Wrong Way to solve problems, but it 
is a technique which is subject to abuse and can often 
be avoided by using function objects instead of 
function names.)


-- 
Steven.




More information about the Python-list mailing list