An operational explanation of Python metaclasses (part 2)

After modifying a class as it's being created (covered in part 1), the next thing you can do with a metaclass is get a chance to do things when instances of the class are created. You do this by defining __call__ on your metaclass:

class MiniMeta(type):
  def __call__(cls, *args, **kwargs):
    return super(MiniMeta, cls).\
           __call__(*args, **kwargs)

class Example(object):
  __metaclass__ = MiniMeta

There are a number of things that you can do with this. One of them (which I first saw in another metaclass tutorial) is handling deferred initialization and setup of something related to the class. Rather than doing this in your metaclass __new__ or __init__, you defer it until the first time an instance of the class is created; this saves you effort in situations where many classes are defined but only a few classes will ever be used to create instances.

Using a metaclass __call__ to customize instance creation runs into the obvious question of why you don't just do the same work in the class's own __init__ method (or in extreme cases, its __new__ method). Probably the right answer is if you have a chunk of common behavior across a bunch of classes and the classes can't easily be put into an inheritance relationship where this functionality can be pulled into a common ancestor or mixin class.

(This use of metaclasses is considered sufficiently interested to get mentioned in passing in the official documentation for __metaclass__.)

PS: __call__ is actually a specific example of a general metaclass power. I'll get to the general power later because it requires more explanation.

Sidebar: a technicality

Strictly speaking using __call__ does not intercept all instance creation, since a sufficiently creative person can still obtain new instances of Example by calling object.__new__() directly. If you're doing something where you have to worry about this, Python is probably the wrong language to write your code in.

These are my WanderingThoughts
(About the blog)

GettingAround
Full index of entries
Recent comments

This is part of CSpace, and is written by ChrisSiebenmann.

* * *

Atom feeds are available; see the bottom of most pages.

This is a DWiki.
(Help)

Categories: links, linux, programming, python, snark, solaris, spam, sysadmin, tech, unix, web

Search:
Written on 17 September 2011.
(Previous | Next)

Page tools: View Source, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Sat Sep 17 00:49:55 2011
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.