2

Im trying to compare types of two objects by using isinstance(obj1, type(obj2)).

However, im not really sure how type infers the typing of an object - or whether theres a chance that the type returned is of an ancestor class.

snufsan
  • 213
  • 1
  • 3
  • 6
  • 3
    `obj2` was created by a call to *some class*, like `obj2 = Foobar()`. `type` returns *that* class object… – deceze Dec 19 '22 at 12:11
  • 1
    Does [this](https://stackoverflow.com/q/1549801/20163209) answer your question? `isinstance` checks for inheritance whereas `type` gives you just the type of the object back – Wolric Dec 19 '22 at 12:13
  • @deceze what if obj2 was obtained as a function parameter with a typing of an ancestor class, would it matter? – snufsan Dec 19 '22 at 12:48
  • 1
    It returns the actual constructor class that constructed the object. How it was passed where is irrelevant and not even data that is attached to the object in any way. – deceze Dec 19 '22 at 12:56
  • "However, im not really sure how type infers the typing of an object" It doesn't infer it, it retrieves the type directly from the object (all objects have a reference to their type). – juanpa.arrivillaga Dec 19 '22 at 12:58
  • @snufsan "what if obj2 was obtained as a function parameter with a typing of an ancestor class, would it matter? " do you mean a *type hint*? No that doesn't matter. Type hints are *hints*. Python is a dynamically typed language, parameters *don't have types* and you can pass any object to any parameter. – juanpa.arrivillaga Dec 19 '22 at 12:59

1 Answers1

1

Given three classes A, B, C. Class B is subclass of A and class C is subclass of B.

class A:
    pass

class B(A):
    pass

class C(B):
    pass

Using type on an object is the same thing as calling obj.__class__. This returns the class to which an instance belongs.

isinstance however also checks for subclasses. So your call isinstance(obj1, type(obj2)) depends on if the two objects are related.

>>> a = A()
>>> b = B()
>>> c = C()
>>> type(c) == type(b)
False
>>> isinstance(c, type(b))
True

Instance c is of type <class '__main__.C'> and b is of type <class '__main__.B'>. So the comparison using type evaluates to False.

A more elaborate example of your approach and using the class directly:

>>> isinstance(c, type(b))  # as C is subclass of B
True
>>> isinstance(c, B)  # using the class directly
True
>>> isinstance(b, type(c))  # as b is of parent class B
False
>>> isinstance(b, C)  # C is subclass of B, thus b is not an instance of C
False
>>> isinstance(c, type(a))  # C is subclass of B which is subclass of A
True
Wolric
  • 701
  • 1
  • 2
  • 18
  • I used `isinstance(obj1, CLS) and isinstance(obj2, CLS)` however its not elegant when CLS is not known prior – snufsan Dec 19 '22 at 12:42
  • Why wouldn't you know the class prior? In what context do you use the `isinstance` check? – Wolric Dec 19 '22 at 12:50
  • It can have one of few types, where all are subclasses of the same class – snufsan Dec 19 '22 at 12:56
  • If they are all subclasses of the same parent class, they all have all the functionalities of that parent class. If however, you need something specific only possible in one of the subclasses, you check again with `isinstance(obj, subclass)` – Wolric Dec 19 '22 at 13:03