indirect function calls and variable variables

Bengt Richter bokr at oz.net
Wed May 21 19:24:13 EDT 2003


On Wed, 21 May 2003 04:35:55 GMT, Randall Smith <randall at tnr.cc> wrote:

>Question:  Is it feasible to make indirect function calls in python?
>
>Example:
>
>
>def f1():
>	blah blah
>	blah blah
>def f2():
>	foo doo
>	doo foo
>def f3():
>	yik yak
>	mee yow
>def fInfinity():
>	yo yo
>	yaw yaw
>
>#what i'm trying to avoid
>def do_f(f):
>	if f == 'f1': f1()
>	if f == 'f2': f2()
>	if f == 'f3': f3()
>	if f == 'fInfinity': youGetThePoint()
>
>#what i'd like to do instead
>def do_f(f):
>	f() # this doesn't work, but maybe you get the point.
>

I'd try something like (note that do_g is more general than do_f, since you can
pass arguments via it -- though I'm not sure __get__ will continue to work the
way I used it. Seems useful though ;-): Of course, with do_g you can't override
the module as is, but we could override it with a special keyword arg, e.g.,
_UseThisModule, if present, and delete it before passing to the named function.
I'll leave that as an excercise ;-)

====< RandallSmith.py >=============================
def f1(): return 'f1 here'
def f2(): return 'f2 here'
def f3(oneArg): return 'f3 here with %r' % oneArg
def f4(*args, **kw): return 'f4 here with %r, %r' %(args, kw)
    
def do_f(f, theModule = __import__(__name__)): # default to current module
    # (disallow non-module overriding arg)
    assert isinstance(theModule, __builtins__.__class__), '2nd do_f arg must be module'
    return getattr(theModule, f)()

def do_g(theModule, f, *args, **kw):
    return getattr(theModule, f)(*args, **kw)
do_g = do_g.__get__(__import__(__name__)) # bind theModule like self in a bound method

if __name__ == '__main__':
    def showargs(fn, *args, **kw):
        pieces = [`fn`]
        if args: pieces.append(', '.join(map(repr, args)))
        if kw: pieces.append(', '.join(['%s=%r' % (k,v) for k,v in kw.items()]))
        return ', '.join(pieces)
                   
    for funName, args, kw in zip('f1 f2 f2 f3 f3 f4 f4'.split(),
                            [(), (), ('f2 bad',), (), ('f3 one ok',), (), ('f41', 'f42')],
                            [{}, {}, {},         {}, {},            {}, {'f4key':'f4val'}]):
        print '    do_f(%s) =>' % showargs(funName, *args, **kw),
        try:
            print do_f(funName, *args, **kw)
        except Exception, e:
            print '\n%s: %s' % (e.__class__.__name__, e)
        print '    do_g(%s) =>' % showargs(funName, *args, **kw),
        try:
            print do_g(funName, *args, **kw)
        except Exception, e:
            print '\n%s: %s' % (e.__class__.__name__, e)
====================================================
Result of running it:

[15:56] C:\pywk\clp>RandallSmith.py
    do_f('f1') => f1 here
    do_g('f1') => f1 here
    do_f('f2') => f2 here
    do_g('f2') => f2 here
    do_f('f2', 'f2 bad') =>
AssertionError: 2nd do_f arg must be module
    do_g('f2', 'f2 bad') =>
TypeError: f2() takes no arguments (1 given)
    do_f('f3') =>
TypeError: f3() takes exactly 1 argument (0 given)
    do_g('f3') =>
TypeError: f3() takes exactly 1 argument (0 given)
    do_f('f3', 'f3 one ok') =>
AssertionError: 2nd do_f arg must be module
    do_g('f3', 'f3 one ok') => f3 here with 'f3 one ok'
    do_f('f4') => f4 here with (), {}
    do_g('f4') => f4 here with (), {}
    do_f('f4', 'f41', 'f42', f4key='f4val') =>
TypeError: do_f() takes at most 2 non-keyword arguments (3 given)
    do_g('f4', 'f41', 'f42', f4key='f4val') => f4 here with ('f41', 'f42'), {'f4key': 'f4val'}

>
>
>While I'm at it, can Python do variable variables?
>In PHP:
>	$var = 'hey'
>	$$var = 'dude'
>
>	echo $dude
>
>	output: hey
>
>I used this alot in PHP.  Is there a way to do it in Python?
Probably, but I'm not sure what you mean.

Regards,
Bengt Richter




More information about the Python-list mailing list