14

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?

4 Answers 4

18

Explanation

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.

Solutions

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).

Sign up to request clarification or add additional context in comments.

3 Comments

@E.Beach I expected that, so I've added the way to compare them without initialization.
@E.Beach anyway, added the extra explanation
Best examples I've seen so far! Thanks for omitting unnecessary stuff like the class body.
10

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.

Comments

3

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

Comments

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.