Simplifying anonymous inner classes?

Peter Otten __peter__ at web.de
Sat Nov 1 08:44:41 EDT 2008


Tim Chase wrote:

> I've got code similar to the following
> 
>   class Action:
>     def __init__(self, ...):  pass
>     def __call__(self, ...):  pass
>     def get_help(self, ...):  pass
> 
>   class Backend:
>     class _Load(Action):
>       def __init__(self, ...): pass # override1
>       def __call__(self, ...): pass # override1
>       def get_help(self, ...): pass # override1
>     load = _Load(...)
>     class _Run(Action):
>       def __call__(self, ...): pass # override2
>       def get_help(self, ...): pass # override2
>     run = _Run(...)
> 
>   class DatabaseBackend(Backend):
>     class _Frob(Action):
>       def __init__(self, ...): pass # override3
>       def __call__(self, ...): pass # override3
>       def get_help(self, ...): pass # override3
>     frob = _Frob(...)
> 
> In certain other languages, I might reach for an anonymous inner
> class -- however, I don't see any way to do something like
> 
>   class Backend:
>     load = (class Action:
>       def __init__(self, ...): pass # override1
>       def __call__(self, ...): pass # override1
>       def get_help(self, ...): pass # override1
>       )(...args to __init__...)
>     run = ...
> 
> It seems silly to define the inner classes _Load and _Run just to
> create a single instance of them (and for all it matters the
> _Load and _Run could be promptly deleted from the containing
> namespace immediately after instantiation).  Method
> implementations are sufficiently complex that a lambda won't
> suffice (or if they would, they're beyond my know-how).
> 
> Is there a more Pythonic way to instantiate sub-classes and
> provide instance-specific implementations without the overhead of
> an unused "anonymous" class cluttering my code/namespace?

Python 2.6 has class decorators:

>>> class instantiate(object):
...     def __init__(self, *args):
...             self.args = args
...     def __call__(self, class_):
...             return class_(*self.args)
...
>>> class Backend:
...     @instantiate(1,2)
...     class load:
...             def __init__(self, x, y):
...                     self.x = x
...                     self.y = y
...             def __str__(self):
...                     return "load(%s, %s)" % (self.x, self.y)
...
>>> print Backend.load
load(1, 2)

For older Pythons you can put the class into a function:

>>> class instantiate:
...     def __init__(self, *args):
...             self.args = args
...     def __call__(self, make_class):
...             return make_class()(*self.args)
...
>>> class Backend:
...     @instantiate(1,2)
...     def load():
...             class Load:
...                     def __init__(self, x, y):
...                             self.x = x
...                             self.y = y
...                     def __str__(self):
...                             return "load(%s, %s)" % (self.x, self.y)
...             return Load
...
>>> print Backend.load
load(1, 2)

While the class namespace isn't "cluttered" it's all a bit too complex to be
truly pythonic.

Peter



More information about the Python-list mailing list