int.is_integer()

Constant True by definition. Like as_integer_ratio, its value is the shared interface with float — not the answer.

Int methodPython 3.12+Live demo
Common call
value.is_integer()
Returns
True for every int; on a float, True only when it has no fractional part
Replaces
isinstance(v, int) or v == int(v) branching
Watch out
Python 3.12+ only — float has had it since 2.6, int is the late arrival
int.is_integer()
→ bool

Demo

Live evaluation
Try:
Inputs
nintinteger
Output
(5).is_integer()
True

Every case returns True, and that is the whole behaviour — an int is a whole number by construction, so there is no input that could say otherwise. The method is worth knowing because float has the same name: (4.0).is_integer() is True and (4.5).is_integer() is False. Since 3.12 you can ask either type without checking which one you hold.

Common patterns

Accept a whole number of either type
One call covers int and float, with no isinstance branch.
if value.is_integer():
    use_as_index(int(value))
Validate parsed numeric input
JSON gives you ints and floats interchangeably; this normalises the check.
if not qty.is_integer():
    raise ValueError("quantity must be whole")
Filter a mixed numeric sequence
Keeps whole values regardless of how each one was written.
wholes = [v for v in values if v.is_integer()]

Examples

1. Always True
(5).is_integer()
Returns
True
2. Zero too
(0).is_integer()
Returns
True
3. Negatives too
(-7).is_integer()
Returns
True
4. Float that is whole
(4.0).is_integer()
Returns
True
5. Float that is not
(4.5).is_integer()
Returns
False
6. The useful contrast
[v.is_integer() for v in (4, 4.0, 4.5)]
Returns
[True, True, False]

Pitfalls

1. It does not test the type
The name reads like an isinstance check, but it asks whether the VALUE is whole. A float returns True when it has no fractional part, so is_integer() being True tells you nothing about whether you hold an int.
Not a type check
v = 4.0
v.is_integer()
True # still a float
Check the type
isinstance(v, int)
False
2. Python 3.12 or newer only
float has had is_integer since 2.6, so the call looks portable until an int reaches it on an older interpreter. That is exactly the mixed-type case the method was added to serve, which makes the failure easy to miss in testing.
Fails on 3.11
(5).is_integer()
AttributeError: 'int' object has no attribute 'is_integer'
Portable form
float(v).is_integer()
True # works everywhere
3. bool is an int, so it answers too
True and False are ints in Python, so they inherit the method and report True. Harmless until a stray boolean slips through a numeric validation path unnoticed.
Booleans pass
True.is_integer()
True
Exclude bool
not isinstance(v, bool) and v.is_integer()
False for booleans

When to use

Use it
  • Numeric code that accepts int and float interchangeably
  • Validating that a parsed number is whole before using it as a count or index
  • Replacing v == int(v) checks, which fail on inf and nan
Reach for something else
  • You already know the value is an int — the answer is always True
  • You actually want a type check → isinstance
  • Supporting Python 3.11 or older → call float(v).is_integer() instead

Notes

Complexity
O(1) — returns a constant
Return
The singleton True; never False for any int
CPython impl
Objects/longobject.c :: int_is_integer
Memory
No allocation — True is a singleton
Thread-safe
Yes — ints are immutable

FAQ

So int and float present the same interface. Before 3.12 you had to write isinstance(v, int) or v == int(v) to handle both; now one call covers either. The constant answer on int is the price of that symmetry.

[v.is_integer() for v in (4, 4.0, 4.5)]
# [True, True, False]

History

3.12
int.is_integer added, matching the float method that has existed since 2.6.