Why does the class definition's metaclass keyword argument accept a callable?
<h2>Background</h2>

<p>The Python 3 <a href="https://docs.python.org/3.6/reference/datamodel.html#determining-the-appropriate-metaclass">documentation</a> clearly describes how the metaclass of a class is determined:</p>

<blockquote>
  <ul>
  <li>if no bases and no explicit metaclass are given, then type() is used</li>
  <li>if an explicit metaclass is given and it is not an instance of type(), then it is used directly as the metaclass</li>
  <li>if an instance of type() is given as the explicit metaclass, or bases are defined, then the most derived metaclass is used</li>
  </ul>
</blockquote>

<p>Therefore, according to the second rule, it is possible to specify a metaclass using a callable.  E.g.,</p>

<pre><code>class MyMetaclass(type):
    pass

def metaclass_callable(name, bases, namespace):
    print("Called with", name)
    return MyMetaclass(name, bases, namespace)

class MyClass(metaclass=metaclass_callable):
    pass

class MyDerived(MyClass):
    pass

print(type(MyClass), type(MyDerived))
</code></pre>

<h2>Question 1</h2>

<p>Is the metaclass of <code>MyClass</code>: <code>metaclass_callable</code> or <code>MyMetaclass</code>?  The second rule in the documentation says that the provided callable "is used directly as the metaclass".  However, it seems to make more sense to say that the metaclass is <code>MyMetaclass</code> since</p>

<ul>
<li><code>MyClass</code> and <code>MyDerived</code> have type <code>MyMetaclass</code>,</li>
<li><code>metaclass_callable</code> is called once and then appears to be unrecoverable,</li>
<li>derived classes do not use (as far as I can tell) <code>metaclass_callable</code> in any way (they use <code>MyMetaclass</code>).</li>
</ul>

<h2>Question 2</h2>

<p>Is there anything you can do with a callable that you can't do with an instance of <code>type</code>?  What is the purpose of accepting an arbitrary callable?</p>

<p>Regarding your first question the metaclass should be <code>MyMetaclass</code> (which it's so):</p>

<pre><code>In [7]: print(type(MyClass), type(MyDerived))
&lt;class '__main__.MyMetaclass'&gt; &lt;class '__main__.MyMetaclass'&gt;
</code></pre>

<p>The reason is that if the metaclass is not an instance of type python calls the methaclass by passing these arguments to it <code>name, bases, ns, **kwds</code> (see <code>new_class</code>) and since you are returning your real metaclass in that function it gets the correct type for metaclass.</p>

<p>And about the second question:</p>

<blockquote>
  <p>What is the purpose of accepting an arbitrary callable?</p>
</blockquote>

<p>There is no special purpose, <strong>it's actually the nature of metaclasses</strong> which is because that making an instance from a class always calls the metaclass by calling it's <code>__call__</code> method:</p>

<pre><code>Metaclass.__call__()
</code></pre>

<p>Which means that you can pass any callable as your metaclass. So for example if you test it with a nested function the result will still be the same:</p>

<pre><code>In [21]: def metaclass_callable(name, bases, namespace):
             def inner():
                 return MyMetaclass(name, bases, namespace)
             return inner()
   ....: 

In [22]: class MyClass(metaclass=metaclass_callable):
             pass
   ....: 

In [23]: print(type(MyClass), type(MyDerived))
&lt;class '__main__.MyMetaclass'&gt; &lt;class '__main__.MyMetaclass'&gt;
</code></pre>

<hr>

<p>For more info here is how Python crates a class:</p>

<p>It calls the <code>new_class</code> function which it calls <code>prepare_class</code> inside itself, then as you can see inside the <code>prepare_class</code> python calls the <code>__prepare__</code> method of the appropriate metaclass, beside of finding the proper meta (using <code>_calculate_meta</code> function ) and creating the appropriate namespace for the class.</p>

<p>So all in one here is the hierarchy of executing a metacalss's methods:</p>

<ol>
<li><code>__prepare__</code> <sup>1</sup></li>
<li><code>__call__</code></li>
<li><code>__new__</code></li>
<li><code>__init__</code></li>
</ol>

<p>And here is the source code:</p>

<pre><code># Provide a PEP 3115 compliant mechanism for class creation
def new_class(name, bases=(), kwds=None, exec_body=None):
    """Create a class object dynamically using the appropriate metaclass."""
    meta, ns, kwds = prepare_class(name, bases, kwds)
    if exec_body is not None:
        exec_body(ns)
    return meta(name, bases, ns, **kwds)

def prepare_class(name, bases=(), kwds=None):
    """Call the __prepare__ method of the appropriate metaclass.

    Returns (metaclass, namespace, kwds) as a 3-tuple

    *metaclass* is the appropriate metaclass
    *namespace* is the prepared class namespace
    *kwds* is an updated copy of the passed in kwds argument with any
    'metaclass' entry removed. If no kwds argument is passed in, this will
    be an empty dict.
    """
    if kwds is None:
        kwds = {}
    else:
        kwds = dict(kwds) # Don't alter the provided mapping
    if 'metaclass' in kwds:
        meta = kwds.pop('metaclass')
    else:
        if bases:
            meta = type(bases[0])
        else:
            meta = type
    if isinstance(meta, type):
        # when meta is a type, we first determine the most-derived metaclass
        # instead of invoking the initial candidate directly
        meta = _calculate_meta(meta, bases)
    if hasattr(meta, '__prepare__'):
        ns = meta.__prepare__(name, bases, **kwds)
    else:
        ns = {}
    return meta, ns, kwds


def _calculate_meta(meta, bases):
    """Calculate the most derived metaclass."""
    winner = meta
    for base in bases:
        base_meta = type(base)
        if issubclass(winner, base_meta):
            continue
        if issubclass(base_meta, winner):
            winner = base_meta
            continue
        # else:
        raise TypeError("metaclass conflict: "
                        "the metaclass of a derived class "
                        "must be a (non-strict) subclass "
                        "of the metaclasses of all its bases")
    return winner
</code></pre>

<hr>

<p><sub>
1. Note that it get called implicitly inside the <em>new_class</em> function and before the return.
</sub></p>

python class python-3.x metaclass