Ian Bicking: the old part of his blog

More on decorators

After reading through the thread on Python-Dev about the new @decorator syntax, it seems like Guido's mind is set, if only from being exhausted by the discussion (14 months of discussion, it seems). This syntax will go out in 2.4a2, though until 2.4rc1 goes out, I'm guessing it's not set in stone.

One thought that occurred to me concerning JP Calderone's suggestion, and one which is very similar to Phillip Eby's suggestion, is that they don't need to be hacks. Well, they need to be hacks now, just like implements() and advise() are hacks now.

So here's another suggestion. decorate() and friends (I like "decorate" much more than Phillip's terse "as") return a specific kind of object. This object is identified by a special attribute, like __metaconstructor__. There is precedence in descriptors, which are identified by special attributes (__get__ and __set__).

Whenever such an object shows up at the top level in a class, it is given access to the class. When, how, or where I'm not sure. In the case of decorators, it needs more access than the standard metaclass mechanism provides, since it needs to know what function was defined after it. In other cases, like interfaces, it would probably be sufficient for the object to work on the constructed class.

The result is something that isn't a hack, and opens up a lot of other possibilities, decorators being just one. Too many possibilities? Maybe. Too hard to notice? I actually think this isn't a problem, because the expressions don't make sense in a class statement except in this case. For instance:

class Foo(object):
    implements(IFoo)
Until people started these frame hacks there were never any statements in a class definition that looked like implements(IFoo). The only reason you'd want to do this is if you wanted the class scope to be available in the expression list, which is an uncommon requirement. Why run something, throw away the value, and execute the whole thing in the scope of a class that does not yet exist? Which is to say, I think these statements are distinctive.

Much like classmethod isn't syntax (it's just a useful builtin), maybe we don't need more syntax here either.

Created 03 Aug '04
Modified 14 Dec '04

Comments:

@something is ugly and unpythonic imho. Don't know if anybody has mentioned it, but I'd go with the Decorator-Block syntax, easy to spot, easy to read, and saves lot of typing.

decorator require_int:
def foo( a, b ): pass
def bar( a, b ): pass
# Florian Bösch

Would you care to guess how many emails have been exchanged on this topic? Thousands, easily. What we emphatically do not need at this point are more "what about this syntax?" ideas...
# Michael Hudson

If all that debate didn't lead anywhere, then maybe the question itself was incorrectly formed.
# Ian Bicking

For such a corner-case feature, the amount of energy wasted on this topic is immeasurable. Let's fix hasattr to not mask all errors instead... or get a nicer process module (PEP 324) or *anything* else but argue about syntax of a language feature that only 1% of Python users are going to want to ever know about.
# Chris McDonough