Factory function with keyword arguments

George Sakkis george.sakkis at gmail.com
Sun Sep 23 01:34:01 EDT 2007


On Sep 22, 10:53 pm, Steven D'Aprano <st... at REMOVE-THIS-
cybersource.com.au> wrote:
> I'm writing a factory function that needs to use keywords in the produced
> function, not the factory. Here's a toy example:
>
> def factory(flag):
>     def foo(obj, arg):
>         if flag:
>             # use the spam keyword to method()
>             return obj.method(spam=arg)
>         else:
>             # use the ham keyword
>             return obj.method(ham=arg)
>     return foo
>
> Problem: the test of which keyword to use is done every time the produced
> function is called, instead of once, in the factory.
>
> I thought of doing this:
>
> def factory(flag):
>     if flag: kw = 'spam'
>     else: kw = 'ham'
>     def foo(obj, arg):
>         kwargs = dict([(kw, arg)])
>         return obj.method(**kwargs)
>     return foo
>
> Is this the best way of doing this? Are there any alternative methods
> that aren't risky, slow or obfuscated?

Unless I'm missing something, the obvious way is to move the flag
check outside the function and have two definitions of foo:

def factory(flag):
    if flag: # use the spam keyword to method()
        def foo(obj, arg):
            return obj.method(spam=arg)
    else: # use the ham keyword
        def foo(obj, arg):
            return obj.method(ham=arg)
    return foo

Now if foo is more than a line or two and the only difference the flag
makes is the keyword argument, you can either factor the common part
out in another function called by foo or (if performance is crucial)
create foo dynamically through exec:

def factory(flag):
    kw = flag and 'spam' or 'ham'
    exec '''def foo(obj, arg):
                return obj.method(%s=arg)''' % kw
    return foo


George




More information about the Python-list mailing list