[Python-Dev] PEP 343: Context managers a superset of decorators?

Eric Sumner kd5bjo at gmail.com
Mon Feb 13 01:19:46 CET 2006


Forgive me if someone has already come up with this; I know I am
coming to the party several months late.  All of the proposals for
decorators (including the accepted one) seemed a bit kludgey to me,
and I couldn't figure out why.  When I read PEP 343, I realized that
they all provide a solution for an edge case without addressing the
larger problem.

If context managers are provided access to the contained and
containing namespaces of their with statement, they can perform the
same function that decorators do now.  A transforming class could be
implemented as:

    ## Code Start -------------------------------------------------
    class DecoratorContext(object):
        def __init__(self, func): self.func = func
        def __context__(self): return self
        def __enter__(self, contained, containing): pass
        def __exit__(self, contained, containing):
            for k,v in contained.iteritems():
                containing[k] = self.func(v)
    ## Code End ---------------------------------------------------

With this in place, decorators can be used with the with statement:

    ## Code Start -------------------------------------------------
    classmethod = DecoratorContext(classmethod)

    class foo:
        def __init__(self, ...): pass
        with classmethod:
            def method1(cls, ...):
                pass
            def method2(cls, ...):
                pass
    ## Code End ---------------------------------------------------

The extra level of indention could be avoided by dealing with multiple
block-starting statements on a line by stating that all except the
last block contain only one statement:

    ## Code Start -------------------------------------------------
    classmethod = DecoratorContext(classmethod)

    class foo:
        def __init__(self, ...): pass
        with classmethod: def method1(cls, ...):
            pass
        with classmethod: def method2(cls, ...):
            pass
    ## Code End ---------------------------------------------------

I will readily admit that I have no idea how difficult either of these
suggestions would be to implement, or if it would be a good idea to do
so.  At this point, they are just something to think about

  -- Eric Sumner


More information about the Python-Dev mailing list