module wide metaclass for new style classes

Peter Otten __peter__ at web.de
Sun Dec 17 02:53:30 EST 2006


Daniel Nogradi wrote:

> I used to have the following code to collect all (old style) class
> names defined in the current module to a list called reg:
> 
> 
> def meta( reg ):
>     def _meta( name, bases, dictionary ):
>         reg.append( name )
>     return _meta
> 
> reg = [ ]
> __metaclass__ = meta( reg )
> 
> class c1:
>     pass
> 
> class c2:
>     pass
> 
> print reg

That code does not create classes. Here's a slightly simplified version:

>> reg = []
>>> def __metaclass__(name, bases, dict):
...     reg.append(name)
...
>>> class A: pass
...
>>> reg
['A']
>>> A is None 
True # oops!

> This would correctly print [ 'c1', 'c2' ]. Now I would like to switch
> to new style classes but replacing class c1: and class c2: by class
> c1(object): and class c2(object): doesn't work because the metaclass
> associated with object will be called and not mine. Of course if I
> would add __metaclass__ = meta(reg)  to all class definitions that
> would work, but how do I do this on the module level?

If present, __metaclass__ serves as a factory for classes without an
explicit base class. For example,

__metaclass__ = type

would turn c1 and c2 into newstyle classes (that inherit from object).
If you want side effects you can wrap the metaclass into a function:

>>> reg = []
>>> def __metaclass__(name, bases, dict):
...     reg.append(name)
...     return type(name, bases, dict)
...
>>> class A: pass
...
>>> class B: pass
...
>>> reg
['A', 'B']
>>> issubclass(A, object)
True

Peter




More information about the Python-list mailing list