[Python-Dev] [Python-checkins] peps: PEP 422 rewrite to present an idea that a) isn't crazy and b) it turns out (original) (raw)

PJ Eby pje at telecommunity.com
Wed Jun 6 23:32:41 CEST 2012


+1 on the PEP. FWIW, it may be useful to note that not only has the pattern of having a class-level init been proposed before, it's actually used: Zope has had class_init and used it as a metaclass alternative since well before Thomas Heller's proposal.

And in my case, about 80% of my non-dynamic metaclass needs are handled by using a metaclass whose sole purpose is to provide me with class_init, class_new, and class_call methods so they can be defined as class methods instead of as metaclass methods. (Basically, it lets me avoid making new metaclasses when I can just define class*_ methods instead. The other use cases are all esoterica like object-relational mapping, singletons and pseudo-singletons. etc.)

So, the concept is a decades-plus proven alternative to metaclasses for low-hanging metaclassy behavior.

This new version of the PEP does offer one challenge to my motivating use case, though, and that's that hooking init_class means any in-body decorators have to occur after any init_class definition, or silent failure will occur. (Because a later definition of init_class will overwrite the dynamically added version.)

While this challenge existed for the metaclass hook, it was by convention always placed at the top of the class, or very near to it. After all, knowing what metaclass a class is, is pretty important, and not done very often. Likewise, had the previous version of the PEP been used, it was unlikely that anybody would bury their decorators list near the end of the class! The init_class method, on the other hand, can quite rightly be considered a minor implementation detail internal to a class that might reasonably be placed late in the class definition.

This is a relatively small apprehension, but it makes me slightly prefer the previous version to this one, at least for my motivating use case. But I'll admit that this version might be better for Python-as-a-whole than the previous version. Among other things, it makes my "classy" metaclass (the one that adds class_init, class_call, etc.) redundant for its most common usage (class_init).

I'm tempted to suggest adding a call_class to the mix, since in grepping my code to check my less-esoteric metaclass use cases just now, I find I implement class_call methods almost as often as class_init ones, but I suspect my use cases are atypical in this regard. (It's mostly used for things where you want to hook instance creation (caches, singletons, persistence, O-R mapping) while still allowing subclasses to define new and/or init without needing to integrate with the tricky bits.)

(To be clear, by esoteric, I mean cases where I'm making classes that act like non-class objects in some regard, like a class that acts as a mapping or sequence of its instances. If all you're doing is making a class with a sprinkling of metaprogramming for improved DRYness, then class_init and class_call are more than enough to do it, and a full metaclass is overkill.) -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.python.org/pipermail/python-dev/attachments/20120606/b29273e8/attachment.html>



More information about the Python-Dev mailing list