title: Why should I use the __prepare__ method to get a class' namespace?
body: <p><strong>Note</strong> <em>This question is not about the Python 3 <code>Enum</code> data type, it's just the example I'm using.</em></p>
  
  <p>With <a href="https://www.python.org/dev/peps/pep-3115/" rel="noreferrer">PEP 3115</a> Python 3 added the <a href="https://docs.python.org/3/reference/datamodel.html#preparing-the-class-namespace" rel="noreferrer"><code>__prepare__</code></a><sup>1</sup> method to <code>type</code> for the purpose of allowing a custom namespace to be used when creating classes.  For example, the new <code>Enum</code> data type uses <code>__prepare__</code> to return an instance of the private <code>_EnumDict</code> for use as the new <code>Enum</code> class' namespace.</p>
  
  <p>However, I have seen several examples on SO<sup>2</sup> of <code>EnumMeta</code> being subclassed, creating a new namespace for the class in the metaclass <code>__new__</code> method, but instead of calling the <code>__prepare__</code> method to acquire that new namespace, <code>type(clsdict)()</code> is used instead.  Are there any risks to doing it this way?</p>
  
  <hr>
  
  <p><sup>1</sup>  The signature for <code>__prepare__</code>:</p>
  
  <pre><code>@classmethod
  def __prepare__(metacls, cls, bases, **kwds):
  </code></pre>
  
  <p>and for <code>__new__</code>:</p>
  
  <pre><code>def __new__(metacls, cls, bases, clsdict, **kwds):
  </code></pre>
  
  <hr>
  
  <p><sup>2</sup>  Example using <code>type(clsdict)</code>:</p>
  
  <p>from <a href="https://stackoverflow.com/a/43100224/208880">this answer</a></p>
  
  <pre><code>class CountryCodeMeta(enum.EnumMeta):
      def __new__(metacls, cls, bases, classdict):
          data = classdict['data']
          names = [(country['alpha-2'], int(country['country-code'])) for country in data]
  
    --&gt;   temp = type(classdict)()
          for name, value in names:
              temp[name] = value
  
          excluded = set(temp) | set(('data',))
          temp.update(item for item in classdict.items() if item[0] not in excluded)
  
          return super(CountryCodeMeta, metacls).__new__(metacls, cls, bases, temp)
  </code></pre>