Assuming a function (with an if-elif
chain) defined such as:
def is_integer(num):
if isinstance(num, float):
return num.is_integer()
elif isinstance(num, int):
return True
else:
return False
Which, is coincidentally equivalent to:
def is_integer(num):
if isinstance(num, float):
return num.is_integer()
if isinstance(num, int):
return True
return False
How it works
Here is the pseudo-code for the above logic.
- If
num
is (or is subclass of) a float:
- return
True
if it represents an integer value, such as 7.0
- else, return
False
- If
num
is (or is subclass of) an int, return True
- If
num
is any other type, return False
Inputs
Thus, for the given inputs:
num = 7 --------- it returns True which is undestandable.
Correct, because 7
is an int
type.
Now from the above pseudo-code, we can see:
num = 7.5 -----------it returns False which i didn't get why?
Since type(7.5)
is float, and 7.5.is_integer()
is False
.
num = 7.0 ----------- it also returns True which i didn't get why?
Since type(7.0)
is float, and 7.0.is_integer()
is True
.
num = False ---------- returns True
Since type(False)
is bool, and bool
is a subclass of int
, so we then return True
.
Testing
>>> is_integer(0)
True
>>> is_integer(1234567)
True
>>> issubclass(type(3), int)
True
>>> is_integer(1.2)
False
>>> is_integer(11.01)
False
>>> 3.21.is_integer()
False
>>> is_integer(7.00)
True
>>> 2.0.is_integer()
True
>>> is_integer(True)
True
>>> issubclass(type(False), int)
True
Resolution
can anyone explain what action does this return num.is_integer()
return statement is performing.
It checks if num
, which is a float
value, represents an integer or decimal value such that the part after the decimal point .
is nothing, or 0
.
For example, float.isinteger()
is true for 123.0
since it is a whole number which does not have a fractional part, but is false for 123.45
since the fractional part is .45
, which means that the number represents a floating point value instead of an integer value.
Perhaps this could be better illustrated with the following example:
>>> 7.0 == int(7.0)
True
>>> 7.1 == int(7.1)
False
Note that 7.0.is_integer()
returns True, since casting the float value to an int
does not result in data being lost, whereas int(7.1)
is 7
, hence we have dropped the fractional part which is .1
, and so 7.1 != 7.0
.
the given below code is for checking the given value is integer or not but it also returning true for values like 7.0,5.0, 9.0 which should have been float.
This is correct, it is due to the float.isinteger()
usage as mentioned above, which checks if the float values can be representable as an int
without any data being lost.
To fix this, you can simply return whether isinstance(num, int)
is true:
def is_integer(num):
return isinstance(num, int)
However, the above does not account for bool
values, since as mentioned issubclass(bool, int)
is True. Thus, a check like isinstance(False, int)
will actually return True
.
To update it to return False
for bool values, we can perform a stricter type check, only checking if the type
of num is explicitly an int
:
def is_integer(num):
return type(num) is int
Finally, to check only for int
and custom subclasses of int
, but to exclude bool
or any subclasses of bool
, we can update to first check for a bool
type or subtype, and then check for an int
type or subtype, as shown below.
def is_integer(num):
if isinstance(num, bool):
return False
# else, we *haven't* returned a value yet
return isinstance(num, int)