Different classes made by type with the same name in Python?

python

Solution

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.

Problem

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?

Original source