You are speculating a lot, while Python's minimalist and "Special cases aren't special enough to break the rules." directive, make it easier to understand than that.
In Python2, a __metaclass__ attribute in the class body is used at class creation time to call the "class" that class will be. Ordinarily it is the class named type. To clarify, that moment is after the parser had parsed the class body, after the compiler had compiled it to a code object, and after it was actually run at program run time, and only if __metaclass__ is explicitly provided in that class body.
So that let's check way goes in a case like:
class A(object):
__metaclass__ = MetaA
class B(A):
pass
A has __metaclass__ in its body - MetaA is called instead of type to make it into "class object".
B does not have __metaclass__ in its body. After it is created, if you just try to access the __metaclass__ attribute, it is an attribute as anyother, that will be visible because Python willget it from the superclass A. If you check A.__dict__ you will see the __metaclass__ and if you check B.__dict__ don't.
This A.__metaclass__ attribute is not used at all when B is created. If you change it in A before declaring B will still use the same metaclass as A - because Python does use the type of the parent class as metaclass in the absense of the declaration of an explicit __metaclass__.
To illustrate:
In [1]: class M(type): pass
In [2]: class A(object): __metaclass__ = M
In [3]: print "class: {}, metaclass_attr: {}, metaclass_in_dict: {}, type: {}".format(A.__class__, A.__metaclass__, A.__dict__.get("__metaclass__"), type(A))
class: <class '__main__.M'>, metaclass_attr: <class '__main__.M'>, metaclass_in_dict: <class '__main__.M'>, type: <class '__main__.M'>
In [4]: class B(A): pass
In [5]: print "class: {}, metaclass_attr: {}, metaclass_in_dict: {}, type: {}".format(B.__class__, B.__metaclass__, B.__dict__.get("__metaclass__"), type(B))
class: <class '__main__.M'>, metaclass_attr: <class '__main__.M'>, metaclass_in_dict: None, type: <class '__main__.M'>
In [6]: A.__metaclass__ = type
In [8]: class C(A): pass
In [9]: print "class: {}, metaclass_attr: {}, metaclass_in_dict: {}, type: {}".format(C.__class__, C.__metaclass__, C.__dict__.get("__metaclass__"), type(C))
class: <class '__main__.M'>, metaclass_attr: <type 'type'>, metaclass_in_dict: None, type: <class '__main__.M'>
Furthermore, if you try to just create a class through a call to type instead of using a body with a class statement, __metaclass__ is also just an ordinary attribute:
In [11]: D = type("D", (object,), {"__metaclass__": M})
In [12]: type(D)
type
Summing up thus far: The __metaclass__ attribute in Python 2 is only special if it is explicitly placed in the class body declaration, as part of the execution of the class block statement. It is an ordinary attribute with no special properties afterwards.
Python3 both got rid of this strange "__metaclass__ attribute is no good now", and allowed for further customization of the class body by changing the syntax to specify metaclasses. (It is like declared as if it were a "metaclass named parameter" on the class statement itself)
Now, to the second part of what raised your doubts: if in the __new__ method of the metaclass you call type instead of type.__new__, there is no way Python can "know" type is being called from a derived metaclass. When you call type.__new__, you pass as its first parameter the cls attribute your metaclass's __new__ itself was passed by the runtime: that is what marks the resulting class as being an instance of a subclass of type. That is just like inheritance works for any other class in Python - so "no special behaviors" here:
So, spot the difference:
class M1(type):
def __new__(metacls, name, bases, attrs):
cls = type.__new__(metacls, name, bases, attrs)
# cls now is an instance of "M1"
...
return cls
class M2(type):
def __new__(metacls, name, bases, attrs):
cls = type(name, bases, attrs)
# Type does not "know" it was called from within "M2"
# cls is an ordinary instance of "type"
...
return cls
It can be seen in the interactive prompt:
In [13]: class M2(type):
....: def __new__(metacls, name, bases, attrs):
....: return type(name, bases, attrs)
....:
In [14]: class A(M2): pass
In [15]: type(A)
Out[15]: type
In [16]: class A(M2): __metaclass__ = M2
In [17]: A.__class__, A.__metaclass__
Out[17]: (type, __main__.M2)
(Note that the metaclass __new__ method first parameter is the metaclass itself, therefore more properly named metacls than cls as in your code, and in a lot of code "in the wild")