Metaclasses vs. standard Python reflection?

Alex Martelli aleax at aleax.it
Tue May 6 04:48:31 EDT 2003


Dave Benjamin wrote:

> In article <sSIta.82275$K35.2431544 at news2.tin.it>, Alex Martelli wrote:
> > Not really, because THE "key concept" in AOP is that you do
> > this *transversally* with respect to inheritance hierarchies --
> > modifying existing classes (without changing their source code),
> > rather than creating new classes by inheritance, and ACROSS a
> > swathe of classes not necessarily related by inheritance.
>
> Is this the sort of thing you can do with metaclasses? If so, how?

Not necessarily.  But, it might be.


> I feel pretty comfortable with what I know of AOP, but I still feel very
> confused about metaclasses and if/how they propose a solution to this
> problem.
>
> For instance, all of the metaclass examples I've seen do something like
> this:
>
> class Foo:
>     __metaclass__ = Bar
>
>     # etc.
>
> But this seems to be doing something like subclassing. If the idea is to

It has little to do with subclassing.  A class is an INSTANCE of its
metaclass -- the relation to subclasses is there, but tangential.


> not touch the original source and merely apply "aspects" to it, how would
> you do this in Python? Could you do something like:
>
> import Foo
> import Bar
> Foo.Foo.__metaclass__ = Bar.Bar
>
> and get a new, improved Foo with Bar-like enhancements, or am I off track?

A class object is created by instantiating a metaclass.  The arguments are:
the classname; the tuple of bases for the class; the class dictionary.

So, given an ordinary class Foo.Foo and a metaclass Bar.Bar, you could
built a "bar-ized" version of the former with:

BarFoo = Bar.Bar('BarFoo', Foo.Foo.__bases__, dict(Foo.Foo.__dict__))

However this would not affect the EXISTING class object Foo.Foo.

You could track down the INSTANCES of Foo, or some of them, and
reassign THEIR __class__.  But Foo's own __class__ is generally NOT
reassignable.  If Foo.Foo wasn't yet instantiated of course you could
easily rebind Foo.Foo = BarFoo, so FUTURE instantiations use the new
class with Bar.Bar as its metaclass.


However -- note that if a class object doesn't define __metaclass__ in
its body and has no bases it can use the GLOBAL value of __metaclass__
instead.  Under the right conditions this lets you arrange for use of your
own metaclasses BEFORE you start creating the class objects.  You'd
surely have to rebind 'object' in the builtins to refer to a type using your
own special metaclass, since most newstyle classes inherit from object
rather than using __metaclass__ explicitly.


Alex





More information about the Python-list mailing list