Is this a good use of __metaclass__?

Bruno Desthuilliers bdesth.quelquechose at
Sat May 6 01:21:05 CEST 2006

Joel Hedlund a écrit :
> Hi!
> I need some input on my use of metaclasses since I'm not sure I'm using 
> them in a pythonic and graceful manner. I'm very grateful for any tips, 
> pointers and RTFMs I can get from you guys.
> Below, you'll find some background info and an executable code example.
> In the code example I have two ways of doing the same thing. The problem 
> is that the "Neat" version doesn't work, and the "Ugly" version that 
> works gives me the creeps.
> The "Neat" version raises a TypeError when I try the multiple 
> inheritance (marked with comment in the code):
> Traceback (most recent call last):
>   File "/bioinfo/yohell/pybox/gridjs/gridjs-2.0/", line 132, in ?
>     class FullAPI(JobAPI, UserAPI, AdminAPI):
>   File "/bioinfo/yohell/pybox/gridjs/gridjs-2.0/", line 43, in 
> __new__
>     return type.__new__(cls,classname,bases,classdict)
> TypeError: Error when calling the metaclass bases
>     metaclass conflict: the metaclass of a derived class must be a 
> (non-strict) subclass of the metaclasses of all its bases

> In the "Ugly" version, I'm changing the metaclass in the global scope 
> between class definitions, 


> and that gives me bad vibes.
> What should I do? Is there a way to fix my "Neat" solution? Is my "Ugly" 
> solution in fact not so horrid as I think it is? Or should I rethink the 
> whole idea? Or maybe stick with decorating manually (or in 
> BaseAPI.__init__)?

I'd go for 'manually decorating' anyway. Metaclasses can be really handy 
for framework-like stuff, but for the use case you describe, I think the 
  explicit decorator option is much more, well, explicit - and also more 
flexible - than metaclass black magic. This may also help you 
distinguish 'published' API from implementation (which is what CherryPy 
do). And finally, this may let you organize your code more freely - you 
can mix methods needing different decorators in a same class.

Also, and FWIW, you may want to favor composition-delegation (which is a 
piece of cake in Python, see below...) over inheritance. This is more 
flexible. You would then have a 'server' class that just provides common 
services and dispatch to specialized objects.

class Dispatcher(object):
   def __init__(self, delegates):
     self._delegates = delegates

  def __getattr__(self, name):
    for delegate in self._delegates:
        return getattr(delegate, name):
      except AttributeError:
     err = "object '%s' has no attribute '%s'" \
           % (self.__class__.__name__, name)
     raise AttributeError(err)

# note that you may want to reorganize your code differently
# if you go for explicit decorators
d = Dispatcher(JobApi, UserApi, AdminApi)

My 2 cents...

More information about the Python-list mailing list