Matina G
Matina G

Reputation: 1582

Inheritance and isinstance

I just noticed that

isinstance(myob, MyClass) 

does not only return True when myob is an instance of MyClass but also if myob is an instance of a class that inherits from MyClass.

To be more clear, consider the following:

class Book(object):
    def __init__(self, cover)
        self._cover = cover

class Novel(Book):
    def __init__(self, cover, category):
        Book.__init__(self, cover)
        self._category = category

When instanciating Novel as follows:

novel = Novel('hardcover', 'police')

then

print(isinstance(novel, Book))

and

print (isinstance(novel , Novel))

both print True.

Why is that so? In my sense, novel is a Novel instance, not a Book one...

Also, relevant to this :

In order to get the "grand-mother" (sic) class, I do:

print(novel.__class__.__bases__)

Is there a more direct way?

Upvotes: 0

Views: 7143

Answers (2)

timgeb
timgeb

Reputation: 78690

This transitive behavior is how it should work intuitively ...

>>> class Text:
...:    pass
...:
...:
>>> class Book(Text):
...:    pass
...:
...:
>>> class Novel(Book):
...:    pass
...:
...:
>>> n = Novel()
>>> isinstance(n, Novel)
>>> True
>>> isinstance(n, Book)
>>> True
>>> isinstance(n, Text)
>>> True

... because a Novel is-a Novel, but also is-a Book and is-a Text.

If you want to know whether a class (or instance of a class) is a direct ancestor of another class, you can use the __subclasses__ method of class objects.

>>> Text.__subclasses__()
>>> [__main__.Book]
>>> Book.__subclasses__()
>>> [__main__.Novel]
>>> Novel.__subclasses__()
>>> []
>>> 
>>> Novel in Text.__subclasses__()
>>> False
>>> type(n) in Text.__subclasses__()
>>> False
>>> Novel in Book.__subclasses__()
>>> True
>>> type(n) in Book.__subclasses__()
>>> True

edit: YourClass.__bases__ also gives you all direct parent classes.

>>> Novel.__bases__
>>> (__main__.Book,)

Upvotes: 6

bruno desthuilliers
bruno desthuilliers

Reputation: 77902

Inheritance is "is a" relationship - if Duck inherit from Bird then obviously a duck (instance of Duck) is ALSO a bird (instance of Bird), so the behaviour you observe is really the expected one (and this holds for all class-based OOPLs).

If you want to check the exact type of an object, you can get it using type(obj) - which will return the class of object - and do an identity test against the desired class, ie:

obj = 42
print(type(obj) is int)

Upvotes: 4

Related Questions