title: Python 2.7 - Is this a valid use of __metaclass__?
body: <p>The problem is as follows. There's a Base class that will be extended by
  several classes which may also be extended.</p>
  
  <p>All these classes need to initialize certain class variables. By the nature of the problem, the initialization should be incremental and indirect. The "user" (the programmer writing Base extensions) may want to "add" certain "config" variables, which may or may not have a (Boolean) property "xdim", and provide default values for them. The way this will be stored in class variables is implementation-dependent. The user should be able to say "add these config vars, with these defaults, and this xdim" without concerning herself with such details.</p>
  
  <p>With that in mind, I define helper methods such as:</p>
  
  <pre><code>class Base(object):
      @classmethod
      def addConfig(cls, xdim, **cfgvars):
          """Adds default config vars with identical xdim."""
          for k,v in cfgvars.items():
              cls._configDefaults[k] = v
          if xdim:
              cls._configXDims.update(cfgvars.keys())
  </code></pre>
  
  <p>(There are several methods like <code>addConfig</code>.)</p>
  
  <p>The initialization must have a beginning and an end, so:</p>
  
  <pre><code>import inspect
  class Base(object):
      @classmethod
      def initClassBegin(cls):
          if cls.__name__ == 'Base':
              cls._configDefaults = {}
              cls._configXDims = set()
              ...
          else:
              base = inspect.getmro(cls)[1]
              cls._configDefaults = base._configDefaults.copy()
              cls._configXDims = base._configXDims.copy()
              ...
  
      @classmethod
      def initClassEnd(cls):
          ...
          if 'methodX' in vars(cls):
              ...
  </code></pre>
  
  <p>There are two annoying problems here. For one thing, none of these methods can be called inside a class body, as the class does not exist yet. Also, the initialization must be properly begun and ended (forgetting to begin it will simply raise an exception; forgetting to end it will have unpredictable results, since some of the extended class variables may shine through). Furthermore, the user <strong>must</strong> begin and end the initialization <em>even if there is nothing to initialize</em> (because<code>initClassEnd</code> performs some initializations based on the <em>existence</em> of certain methods in the derived class).</p>
  
  <p>The initialization of a derived class will look like this:</p>
  
  <pre><code>class BaseX(Base):
      ...
  
  BaseX.initClassBegin()
  BaseX.addConfig(xdim=True, foo=1, bar=2)
  BaseX.addConfig(xdim=False, baz=3)
  ...
  BaseX.initClassEnd()
  </code></pre>
  
  <p>I find this kind of ugly. So I was reading about metaclasses and I realized they can solve this kind of problem:</p>
  
  <pre><code>class BaseMeta(type):
      def __new__(meta, clsname, clsbases, clsdict):
          cls = type.__new__(meta, clsname, clsbases, clsdict)
          cls.initClassBegin()
          if 'initClass' in clsdict:
              cls.initClass()
          cls.initClassEnd()
          return cls
  
  class Base(object):
      __metaclass__ = BaseMeta
      ...
  </code></pre>
  
  <p>Now I'm asking the user to provide an optional class method <code>initClass</code> and call <code>addConfig</code> and other initialization class methods inside:</p>
  
  <pre><code>class BaseX(Base):
      ...
  
      @classmethod
      def initClass(cls):
          cls.addConfig(xdim=True, foo=1, bar=2)
          cls.addConfig(xdim=False, baz=3)
          ...
  </code></pre>
  
  <p>The user doesn't even need to know that <code>initClassBegin/End</code> exist.</p>
  
  <p>This works fine in some simple test cases I wrote but I'm new to Python (6 months or so) and I've seen warnings about metaclasses being dark arts to be avoided. They don't seem so misterious to me, but I though I'd ask.
  Is this a justifiable use of metaclasses? It is even correct?</p>
  
  <p><em>NOTE: The question about correctness was not in my mind originally. What happened is that my first implementation seemed to work, but it was subtly wrong. I caught the mistake on my own. It wasn't a typo but a consequence of not understanding completely how metaclasses work; it got me thinking that there might be other things that I was missing, so I asked, unwisely, "Is it even correct?" I wasn't asking anybody to test my code. I should have said "Do you see a problem with this approach?"</em></p>
  
  <p><em>BTW, the error was that initially I did not define a proper <code>BaseMeta</code> class, but just a function:</em></p>
  
  <pre><code>def baseMeta(clsname, clsbases, clsdict):
     cls = type.__new__(type, clsname, clsbases, clsdict)
     ...
  </code></pre>
  
  <p><em>The problem will not show in the initialization of Base; that will work fine. But a class derived from Base will fail, because that class will take its metaclass from the class of Base which is<code>type</code>, not <code>BaseMeta</code>.</em></p>
  
  <p><em>Anyway, my main concern was (and is) about the appropriateness of the metaclass solution.</em></p>
  
  <p>NOTE: The question was placed "on hold", apparently because some members did not understand what I was asking. It seems to me it was clear enough.
  But I'll reword my questions:</p>
  
  <ol>
  <li><p>Is this a justifiable use of metaclasses?</p></li>
  <li><p>Is my implementation of <code>BaseMeta</code> <em>correct</em>? (No, I'm not asking "Does it work?"; it does. I'm asking "Is it in accordance with
  the usual practices?").</p></li>
  </ol>
  
  <p><strong>xyres</strong> had no trouble with the questions. He answered them respectively 'yes' and 'no', and contributed helpful comments and advise. I accepted his response (a few hours after he posted it).</p>
  
  <p>Are we happy now?</p>