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/test.py", line 132, in ? > class FullAPI(JobAPI, UserAPI, AdminAPI): > File "/bioinfo/yohell/pybox/gridjs/gridjs-2.0/test.py", 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
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/204197 > In the "Ugly" version, I'm changing the metaclass in the global scope > between class definitions, Yuck. > 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: try: return getattr(delegate, name): except AttributeError: pass else: 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... -- http://mail.python.org/mailman/listinfo/python-list