Python Forum

Full Version: isinstance() always return true for object type check
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hey guys,

I am currently learning class special methods.
There's my class:

class Time_Cal:

    def __init__(self, hour=0, minute=0, seg=0):
        self.hour = hour
        self.minute = minute
        self.seg = seg

    def __add__(self, other):
        if isinstance(other, Time_Cal):
            return self.__add_sub(other, "addition")
        else:
            raise TypeError("The object is not Time_Cal")

    def __str__(self):
        return str(self.hour) + ":" + str(self.minute) + ":" + str(self.seg)
There's the code in main:
from myTime import Time_Cal

time1 = Time_Cal(5, 45, 12)
time2 = Time_Cal(7, 50, 24)
print("The sum of Time1 and Time2:", str(time1 + time2))
The logic actually works, however, I am now testing the code what if I create my object something like this:
time1 = Time_Cal(5, 45, 12)
time2 = Time_Cal(7, 50, "24")
So time2 is not a Time_Cal object (because one of the argument is not int anymore.)
I am expecting if isinstance(other, Time_Cal) return False so, the code can raise the TypeError.
However, for some reasons, it always return True and enter the next step logic which will cause uncatched exceptions.

Is anyone who can help me out? Thanks
isinstance returns True because time1 and time2 are both Time_Cal objects.
time1 = Time_Cal(5, 45, 12)
time2 = Time_Cal(7, 50, '24')
print(time1, time2)
Output:
5:45:12 7:50:24
time2 may not have a valid seconds value, but it is still a Time_Cal object. If it is important that hour, minute and seg are numbers, you should do that checking where the values are set, not where the values are used. This should cause an error, I would use a TypeError.
time2 = Time_Cal(7, 50, '24')
Maybe something like this:
    def __init__(self, hour=0, minute=0, seg=0):
        if not isinstance(hour, int, float):
            raise TypeError('hour must be a number')
Though I prefer this:
    def __init__(self, hour=0, minute=0, seg=0):
        self.hour = int(hour)
        self.minute = int(minute)
        self.seg = float(seg)
If it acts like a number treat it like a number.

Also your add function is odd. When I add 3 + 2 I don't change 3 to be 5. When I add time1 and time2 I would expect to get a new time that is their sum.
class Time_Cal:
 
    def __init__(self, hour=0, minute=0, seg=0):
        self.hour = int(hour)
        self.minute = int(minute)
        self.seg = float(seg)
        self.normalize()
 
    def normalize(self):
        while self.seg > 60:
        self.minute += self.seg // 60
        self.seg = self.seg % 60
        self.hour += self.minute // 60
        self.minute = self.minute % 60
 
    def __add__(self, other):
        return Time_Cal(
            self.hour + other.hour,
            self.minute + other.minute,
            self.seg + other.seg)

    def __str__(self):
        return str(self.hour) + ":" + str(self.minute) + ":" + str(self.seg)

time1 = Time_Cal(5, 45, 12)
time2 = Time_Cal(7, 50, '24')
print("The sum of Time1 and Time2:", time1 + time2)
Thanks for the detailed explanation! Very helpful!!!


(Jul-22-2020, 06:32 PM)deanhystad Wrote: [ -> ]isinstance returns True because time1 and time2 are both Time_Cal objects.
time1 = Time_Cal(5, 45, 12)
time2 = Time_Cal(7, 50, '24')
print(time1, time2)
Output:
5:45:12 7:50:24
time2 may not have a valid seconds value, tut it is still Time_Cal object. If it is important that hour, minute and seg are numbers, you should do that checking where the values are set, not where the values are used. This should cause an error, I would use a TypeError.
time2 = Time_Cal(7, 50, '24')
Maybe something like this:
    def __init__(self, hour=0, minute=0, seg=0):
        if not isinstance(hour, int, float):
            raise TypeError('hour must be a number')
Though I prefer this:
    def __init__(self, hour=0, minute=0, seg=0):
        self.hour = int(hour)
        self.minute = int(minute)
        self.seg = float(seg)
If it acts like a number treat it like a number.

Also your add function is odd. When I ad 3 + 2 I don't change 3 to be 5. When I add time1 and time2 I would expect to get a new time that is their sum.
class Time_Cal:
 
    def __init__(self, hour=0, minute=0, seg=0):
        self.hour = int(hour)
        self.minute = int(minute)
        self.seg = float(seg)
        self.normalize()
 
    def normalize(self):
        while self.seg > 60:
            self.minute += 1
            self.seg -= 60
        while self.minute > 60:
            self.hour += 1
            self.minute -= 60
 
    def __add__(self, other):
        return Time_Cal(
            self.hour + other.hour,
            self.minute + other.minute,
            self.seg + other.seg)

    def __str__(self):
        return str(self.hour) + ":" + str(self.minute) + ":" + str(self.seg)

time1 = Time_Cal(5, 45, 12)
time2 = Time_Cal(7, 50, '24')
print("The sum of Time1 and Time2:", time1 + time2)