Defining two classes (a base "ClassA" and a subclass "ClassB" in two separate files), gives unexpected results when using Python's isinstance method. Output appears to be impacted by the module name (namespace?) used while running (__main__). This behavior appears on both Python 3.8.5 and 3.10.4.
File ClassA.py contains:
class ClassA:
def __init__(self, id):
self.id = id
def __str__(self) -> str:
class_name = type(self).__name__
return f"{class_name} WITH id: {self.id}"
def main():
from ClassB import ClassB
id = 42
for i, instance in enumerate([ClassA(id), ClassB(id)]):
label = f"{type(instance).__name__}:"
print("#" * 50)
print(f"{label} type: {type(instance)}")
label = " " * len(label) # Convert label to appropriate number of spaces
is_a = isinstance(instance, ClassA)
is_b = isinstance(instance, ClassB)
print(f"{label} is_a/b: {is_a}/{is_b}")
print(f"{label} str: {instance}")
if __name__ == "__main__":
main()
File ClassB.py contains:
from ClassA import ClassA
class ClassB(ClassA):
def __init__(self, id):
super().__init__(id)
self.id *= -1
File main.py contains:
if __name__ == "__main__":
from ClassA import main
main()
The output from running ClassA.py gives:
01: ##################################################
02: ClassA: type: <class '__main__.ClassA'>
03: is_a/b: True/False
04: str: ClassA WITH id: 42
05: ##################################################
06: ClassB: type: <class 'ClassB.ClassB'>
07: is_a/b: False/True
08: str: ClassB WITH id: -42
While the output from running main.py (which calls ClassA.main) gives:
01: ##################################################
02: ClassA: type: <class 'ClassA.ClassA'>
03: is_a/b: True/False
04: str: ClassA WITH id: 42
05: ##################################################
06: ClassB: type: <class 'ClassB.ClassB'>
07: is_a/b: True/True
08: str: ClassB WITH id: -42
Notice how the type of the ClassA instance changes (on Lines 02) from '__main__.ClassA' (when run from ClassA.py) to 'ClassA.ClassA' (when run from main.py). Similarly, the isinstance type checks for ClassA and ClassB (on Lines 07) change from 'False/True' (unexpected) to 'True/True' (desired, expected).
Any comments/suggestions/explanations would be helpful. Thanks.