Reputation: 1857
I have two classes defined in a module classes.py
:
class ClassA(object):
pass
class ClassB(object):
pass
And in another module I am getting the attributes of the module:
import classes
Class1 = getattr(classes, 'ClassA')
Class2 = getattr(classes, 'ClassA')
print type(Class1) == type(Class2)
Class3 = getattr(classes, 'ClassA')
Class4 = getattr(classes, 'ClassB')
print type(Class3) == type(Class4)
Both type comparison are returning True and that's not what I was expecting.
How can I compare class types using python's native type values?
Upvotes: 14
Views: 42946
Reputation: 11009
If you want to check if types are equal then you should use is
operator.
Example: we can create next stupid metaclass
class StupidMetaClass(type):
def __eq__(self, other):
return False
and then class based on it:
in Python 2
class StupidClass(object):
__metaclass__ = StupidMetaClass
in Python 3
class StupidClass(metaclass=StupidMetaClass):
pass
then a simple check
>>> StupidClass == StupidClass
returns False
, while
>>> StupidClass is StupidClass
returns an expected True
value.
So as we can see ==
operator on classes can be overloaded while there is no way (at least simple one) to change is
operator's behavior.
Upvotes: 10
Reputation: 46593
This is why your comparison doesn't work as expected
>>> class ClassA(object):
... pass
...
>>> class ClassB(object):
... pass
...
>>> type(ClassB)
<class 'type'>
>>> type(ClassA)
<class 'type'>
>>> type(ClassA) == type(ClassB)
True
But why do ClassA
and ClassB
have the same type type
? Quoting the docs:
By default, classes are constructed using type(). The class body is executed in a new namespace and the class name is bound locally to the result of type(name, bases, namespace).
Example:
>>> ClassB
<class '__main__.ClassB'>
>>> type('ClassB', (), {})
<class '__main__.ClassB'>
>>> type(ClassB)
<class 'type'>
>>> type(type('ClassB', (), {}))
<class 'type'>
Getting the type of ClassB
is exactly the same as getting the type of type('ClassB', (), {})
, which is type
.
Compare them directly (w/out using the type()
function):
>>> ClassA
<class '__main__.ClassA'>
>>> ClassB
<class '__main__.ClassB'>
>>> ClassA == ClassB
False
or initialize them and compare the types of their objects:
>>> a = ClassA()
>>> b = ClassB()
>>> type(a)
<class '__main__.ClassA'>
>>> type(b)
<class '__main__.ClassB'>
>>> type(a) == type(b)
False
FWIW you can also use is
in place of ==
(for classes).
Upvotes: 18
Reputation: 4319
In addition to the other answers :
Python uses the concept of metaclasses, which are basically "classes of classes". That means, even a Class is an object in Python, which has its own class - accessible using the type
in-build function.
Because ClassA
and ClassB
are by default instances of the same metaclass, the comparisons return True.
If you'd like to know more about metaclasses, this SO post is a good start.
Upvotes: 1
Reputation: 90027
You're comparing the type of the class object, which are all of type 'type'
.
If you just want to compare the classes, compare them directly:
print Class3 == Class4
Upvotes: 3