Simplifying anonymous inner classes?

Arnaud Delobelle arnodel at googlemail.com
Sat Nov 1 10:50:39 EDT 2008


Tim Chase <python.list at tim.thechases.com> writes:

> 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?
>
> Thanks,
>
> -tkc
>
>
> PS: part of the aim is to have properties that can be discovered
> through introspection, know how to provide help on themselves, and
> have a protocol for parameter-discovery for the __call__ method.

Here's a way to do it in python 2.2+:

def instance(*args, **kwargs):
    class MetaInstance(type):
        pass

    class Instance(object):
        __metaclass__ = MetaInstance

    @staticmethod
    def MetaInstance__new__(meta, name, bases, attrs):
        bases = list(bases)
        bases.remove(Instance)
        cls = type(name.capitalize(), tuple(bases), attrs)
        return cls(*args, **kwargs)

    MetaInstance.__new__ = MetaInstance__new__

    return Instance 

How to use it:

>>> class A(object):
...     def foo(self): return 'A.foo'
... 
>>> class b(instance(42), A):
...     def __init__(self, x): print 'This B is given ', x
...     def bar(self): return 'B.bar'
... 
This B is given 42
>>> b.foo()
'A.foo'
>>> b.bar()
'B.bar'
>>> 

(There may be a simpler way to do it, I've just adapted something else
to what you require)

-- 
Arnaud



More information about the Python-list mailing list