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.
The name of the class is an attribute of the class object itself. Normally when you define a class, you bind it to a variable( with the class name ), but the class name will still be stored inside the class object itself.
And in your case, you are making two new objects which are different, but happen to both be classes, and have the same name. And they are not bound to a variable in the namespace the same way a normal class would be.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With