Numbers, types and truthiness
Integers that never overflow, floats that cannot hold 0.1, is against ==, and what Python considers false — with the traps interviewers reach for.
Python has few types and strong opinions about them. Learn the opinions and you stop guessing.
Integers do not overflow
In C or Java, an int is a fixed number of bits and adding one to the largest one wraps around.
In Python, an integer grows as large as your memory allows:
x = 2 ** 200
print(x)
# 1606938044258990275541962092341162602522202993782792835301376
print(len(str(2 ** 10000))) # 3011 digits, no errorThis is genuinely useful in coding rounds. A factorial or a fibonacci question that would need
BigInteger in Java needs nothing in Python. There is no int and long distinction — Python 3
has one integer type.
Floats cannot hold 0.1
This is the single most common "gotcha" question, and the answer has nothing to do with Python:
print(0.1 + 0.2) # 0.30000000000000004
print(0.1 + 0.2 == 0.3) # FalseA float is stored in binary. 0.1 in binary is a repeating fraction, the same way 1/3 is
0.333… in decimal. It gets cut off, so what is stored is very slightly not 0.1. Every
language with IEEE-754 doubles behaves this way — Java, C, JavaScript included.
Two correct fixes, depending on what you need:
# comparing measurements — allow a tolerance
import math
print(math.isclose(0.1 + 0.2, 0.3)) # True
# money — never use float for money
from decimal import Decimal
print(Decimal("0.1") + Decimal("0.2")) # 0.3 (exactly)
print(Decimal("0.1") + Decimal("0.2") == Decimal("0.3")) # TrueNote Decimal("0.1") with a string argument. Decimal(0.1) passes an already-broken float
in and preserves the error faithfully.
Integer division, and what % does to negatives
Python has two division operators:
print(7 / 2) # 3.5 true division, always a float
print(7 // 2) # 3 floor division
print(7 % 2) # 1 remainder// floors — it rounds towards negative infinity, not towards zero. This surprises anyone
coming from C or Java:
print(-7 // 2) # -4 (not -3)
print(-7 % 2) # 1 (not -1)
print(7 % -2) # -1The rule Python keeps is that a % b always has the sign of b, and
(a // b) * b + (a % b) == a always holds. That second identity is why // must floor. In C,
-7 / 2 is -3 and -7 % 2 is -1 — a different, equally consistent choice.
If you want C behaviour, ask for it explicitly:
import math
print(math.trunc(-7 / 2)) # -3, rounds towards zeroThis is a real source of wrong answers in coding rounds involving negative indices or circular arrays. Test one negative case before you submit.
is versus ==
== compares values. is compares identity — whether two names point at the same object.
a = [1, 2]
b = [1, 2]
print(a == b) # True — same contents
print(a is b) # False — two separate listsNow the trap. Small integers and short strings are cached by CPython, so identity accidentally agrees with equality:
x = 256
y = 256
print(x is y) # True — CPython pre-allocates -5..256
x = 257
y = 257
print(x is y) # False in a fresh interpreter sessionThe lesson is not the number 256. It is this: never use is to compare values. Use it for
exactly one thing:
if value is None:
...None is a singleton — there is precisely one None object in a running program — so is None
is both correct and faster than == None. The same applies to is True and is False, though
those are rarely what you actually want.
Truthiness
if x: does not require a boolean. Python asks the object whether it considers itself true.
These are all false:
False, None, 0, 0.0, 0j, "", [], (), {}, set(), range(0)Everything else is true — including "0", "False", [0] and {"": 0}, all of which are
non-empty and therefore true. This gives you the most idiomatic line in Python:
items = []
if not items: # idiomatic
print("nothing here")
if len(items) == 0: # works, reads like a translation from another language
print("nothing here")And one real trap:
def fetch(count=None):
if not count: # WRONG: 0 is a legitimate count
count = 10
return count
print(fetch(0)) # 10 — the caller asked for zero and got ten
def fetch_ok(count=None):
if count is None: # right: only the missing case
count = 10
return count
print(fetch_ok(0)) # 0not count conflates "no value given" with "the value zero". Reach for is None whenever zero
or an empty string is a meaningful input.
Type conversion and checking
int("42") # 42
int("42abc") # ValueError
int(3.9) # 3 — truncates, does not round
round(3.9) # 4
float("3.5") # 3.5
str(42) # "42"
bool("False") # True — a non-empty stringround() has one more surprise: it uses banker's rounding, breaking ties towards the even
number, which reduces bias when you round a large set of values.
print(round(0.5)) # 0
print(round(1.5)) # 2
print(round(2.5)) # 2To check a type, prefer isinstance over type(x) ==, because isinstance accepts subclasses
and a tuple of options:
print(isinstance(True, int)) # True — bool subclasses int
print(isinstance(3, (int, float))) # TrueYes: True == 1 and True + True == 2. bool is a subclass of int. That is a genuine
interview question and the answer is one line long.
What to take into an interview
- Python 3 integers are arbitrary precision — no overflow, no separate
long. 0.1 + 0.2 != 0.3because of binary floating point, in every language. Usemath.isclose, orDecimalfor money.//floors towards negative infinity, so-7 // 2 == -4.a % btakes the sign ofb.iscompares identity,==compares value. Useisonly forNone.- Empty containers, zero and
Noneare falsy.not xandx is Noneare not the same test. boolis a subclass ofint, soTrue + True == 2.