[Python-Dev] @decoration of classes

Jack Diederich jack at performancedrivers.com
Tue Mar 29 02:22:23 CEST 2005

On Mon, Mar 28, 2005 at 09:25:18AM -0800, Michael Chermside wrote:
> Josiah Carlson writes:
>      [... stuff about reST and TeX ...]
> > While I have not used it often, I have done the equivalent of decorating
> > classes; it is as natural (though perhaps not quite as useful initially)
> > as decorating functions,
>      [... stuff about ice cream and sprinkles ...]
> Hmm... the only bit that I found particularly interesting there was the bit
> where you mention that you've used class decorators (without the syntax)
> before.
> What did you use them for? After all, the current state of things is "don't
> bother implementing class decorators because there is no compelling use
> case". If you've got some sample use cases, what were they?
> For my own part, I observe the following. Because a function decorator
> acts after the function object is created, there are limits to what it
> can do to the function. It can add some markup (eg: set properties or
> doc strings). It can "hook" either before or after the function is
> called. Or it can "veto" the function call and do something else
> instead. In the case of function calls, these are pretty much the
> interesting things you would want to do.
> Similarly, because a class decorator acts after the class is created
> there are limits on what it can do. It can modify the class object
> (replacing methods and such). It can add markup. It can replace the
> class with another (perhaps a proxy or some such). But most of these
> are things which are more easily done by a metaclass... and all of
> them *can* be done by metaclasses. The only noticable advantage that
> I see to class decorators over metaclasses is that there's a more
> straightforward way to combine them. And I'm not sure that combining
> metaclasses (or class decorators) is something I want to encourage.
> So I'm inclined to use different tools for modifying functions and
> modifying classes because the ways you want to modify them are
> different, and decorators are "tuned" to what people normally want
> to do with functions (like simple wrapping) while metaclasses are
> "tuned" to what people normally want to do with classes (like support
> for inheritance.

Metaclasses are a muddle because they can do everything a class can do
and more, since metclasses are to classes as classes are to objects.
>From the bottom up:

  get magic methods from their class
  can manipulate non-magic methods and attributes on a per-instance basis
  get magic methods from their metaclass
  can create magic methods and attributes used by objects.
  Plus anything objects can do
  can create magic methods of a class
  can define class methods and attributes
  Plus anything a class can do.

Metaclasses are a muddle because we (the royal we) are used to doing most 
things at the class level.  Defining class methods in a metaclass like this 
probably isn't your regular style

>>> class MetaK(type):
...   def foo(cls): pass
>>> class K:
...   __metaclass__ = MetaK
...   def bar(cls): pass
...   bar = classmethod(bar)
>>> K.foo
<bound method MetaK.foo of <class '__main__.K'>>
>>> K.bar
<bound method MetaK.bar of <class '__main__.K'>>

I'm happy using classmethod instead of writing a metaclass everytime I need 
a classmethod.  I think everyone is class-centric, or we could define static
methods using
class MetaK(type):
  def foo(): pass
  foo = metaclassmethod(foo) # class method of a type is a static method?

Since I've never wanted to set a type's __repr__ I use metaclasses
as a handy place to do mundane class-level manipulations.  I don't actually need
to do type level manipulations.

So that's why I like class decorators, it lets me push type level manipulations
(manipulating a class from its type's __init__ or __new__) down to the class
level where my brain normally hangs out.  I just want to change an object's
behavior and I'd welcome a chance to do it by manipulating the class and
not the class's class (which is the object's class's class, yikes!)


ps, I tried to raise a simliar point at PyCon during Alex Martelli's Q&A
    but got flustered and screwed it all up.

More information about the Python-Dev mailing list