I was playing around with metaclasses in Python and found something very curious. I can create two classes with the same name, but that are actually different objects. See:
>>> def create_class(**data):
... return type('MyClass', (object,), data)
...
>>> A = create_class(x=1, y=2)
>>> B = create_class(x=1, y=2)
>>> A
<class '__main__.MyClass'>
>>> B
<class '__main__.MyClass'>
>>> A == B
False
>>> a = A()
>>> b = B()
>>> type(a)
<class '__main__.MyClass'>
>>> type(b)
<class '__main__.MyClass'>
>>> type(a) == type(b)
False
I thought names within a namespace should be unique. Is it not the case, then?
Names within a namespace are unique, but that doesn't have any bearing on your situation here. Basically there are two different things: "names" and __name__
s. A "name" is a variable in a namespace. A __name__
is just an attribute of a class whose value is "what the class calls itself".
In your code above, MyClass
is a __name__
and A
and B
are names. MyClass
is not a name in the __main__
namespace. The "class __main__.MyClass
" that you're seeing is just the class's __name__
attribute, not an actual variable in a namespace. Normally the class's __name__
will be equal to the name you define it with, but if you create a class programmatically by calling type
as you did, it will still have a __name__
but won't necessarily be accessible via any name in the namespace.
Here's a simple example of the difference:
>>> A = type('MyClass', (object,), {})
>>> MyClass
Traceback (most recent call last):File "<pyshell#3>", line 1, in <module>MyClass
NameError: name 'MyClass' is not defined
Just passing MyClass
to type
doesn't actually create a variable called MyClass
. It is these actual variable names that are unique, not a class's internal notion of its name.
A class is the same as another class if they are the same class object. Even if they have the same __name__
attribute, they can still be different objects.