Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

python

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?

like image 708
erickrf Avatar asked Jul 14 '13 17:07

erickrf


2 Answers

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.

like image 151
BrenBarn Avatar answered Oct 23 '22 16:10

BrenBarn


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.

like image 37
NullData Avatar answered Oct 23 '22 18:10

NullData