Using metaclasses to play with decorators.

Jeff Epler jepler at unpythonic.net
Mon Jun 14 21:10:11 EDT 2004


Here's another way to use metaclasses to specify decorators:
    class O(object):
        __metaclass__ = DecoratedMeta

        def f(cls, x, __decorate__ = [classmethod]):
            return x*x
        def g(x, __decorate__ = [staticmethod]):
            return x**3
        def h(self, x):
            return x

I think this is a terrible abuse, and I would never want to see this
used in real-world code, but that didn't stop me from writing the code
to show how *cough*clever*cough* I am.

Here's the little-tested implementation:

import inspect, types

def decorate(func):
    argnames, _, _, defaults = inspect.getargspec(func)
    try:
        i = argnames.index("__decorate__")
    except ValueError: # x not in list
        return func
    j = i - len(argnames)
    decorators = defaults[j]
    decorators.reverse()
# XXX: Add code here to remove __decorate__ from func's arglist
    for d in decorators:
        func = d(func)
    return func 

def DecoratedMeta(name, bases, ns):
    for k, v in ns.iteritems():
        if not isinstance(v, types.FunctionType):
            continue
        ns[k] = decorate(v)
    return type(name, bases, ns)

if __name__ == '__main__':
    class O(object):
        __metaclass__ = DecoratedMeta

        def f(cls, x, __decorate__ = [classmethod]):
            return x*x
        def g(x, __decorate__ = [staticmethod]):
            return x**3
        def h(self, x):
            return x

    print O.f(3), O.g(4)
    o = O()
    print o.f(5), o.g(6), o.h(7)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 196 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-list/attachments/20040614/08b21c77/attachment.sig>


More information about the Python-list mailing list