Alternative to multi-line lambdas: Assign-anywhere def statements

Chris Angelico rosuav at gmail.com
Sat Jan 24 01:28:41 EST 2015


In some random and rambling discussion about Python, the notion came
up that multi-line lambda functions are often sought as a means of
populating dictionaries and other such structures. Conceptually, "def
foo(...): ..." is broadly equivalent to "foo = FunctionType(...)"; but
the only type of assignment that can be done is to a simple name.
(It's affected by global statements, so it might be global or local,
but still just a simple name.)

The theory was mooted that it would be nice to be able to assign to anything:

cmd = {} # Command dispatch table

def cmd["foo"](*args):
    print("You asked to foo.")

def cmd["bar"](*args):
    print("There's no wine in the bar.")

def cmd["asdf"](*args):
    print("Asdf! Asdf!")

Obviously this doesn't (currently) work syntactically; but in theory,
a decorator ought to be able to do the same job. The question is, can
it be done generically? For the specific case of the dispatch table,
it would be easy enough to make a function that stuffs its argument
into that one specific dictionary:

cmd = {}
def command(func):
    cmd[func.__name__] = func
    return func

@command
def foo(*args):
    print("You asked to foo.")

but this is hardly generic. There's no convenient way to give an
argument to a decorator that says "please assign this here", short of
using some stupid eval hack... is there?

(Incidentally, for a non-generic dispatch table, a callable dict
subclass could be pretty clean:

class DispatchTable(dict):
    """Self-populating dictionary - use this as a function decorator
to stuff functions into it."""
    def __call__(self, func):
        self[func.__name__] = func
        return func

cmd = DispatchTable()

@cmd
def foo(*args):
    print("You asked to foo.")

It's still specific to one exact purpose, though.)

ChrisA



More information about the Python-list mailing list