Alternative to multi-line lambdas: Assign-anywhere def statements
Tim Chase
python.list at tim.thechases.com
Sat Jan 24 07:23:38 EST 2015
On 2015-01-24 17:28, Chris Angelico wrote:
> 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.")
As best I can tell, your question is "is there a better way to do
dispatch tables without duplicating the storage location while
remaining sufficiently generic?"
The closest I've seen is something like cmd.Cmd does where you have a
class and dispatch methods on it with a certain naming convention
(this prevents odd access to dunder methods). Akin to your first
example [reordered from your original post]
> 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!")
It usually looks something like
class Dispatcher(object):
def __getitem__(self, name):
return getattr(self, "do_" + name)
class MyExample(Dispatcher):
def do_hello(self, who):
print("Hello, %s" % who)
def do_goodbye(self, who, feeling):
print("Goodbye, %s. I'm %s to see you go" % (
who, feeling))
mydispatch = MyExample()
mydispatch["hello"]("world")
mydispatch["goodbye"]("cruel world", "sorry")
mydispatch["does not exist"]("give me an AttributeError")
The root Dispatcher object can grow helpful methods like
class Dispatcher(object):
# ...
def get_help(self, name):
return getattr(self, name, "No help for %r" % name)
def __iter__(self):
for name in dir(self):
if name.startswith("do_") and callable(getattr(self, "do_" + name)):
yield name
# ...
def do_hello(self, who):
"Say hello to a person"
# ...
# print out all known methods and their help
for method in mydispatch:
print("%s: %s" % (method, mydispatch.get_help(method_name)))
-tkc
More information about the Python-list
mailing list