Built-in Types

Updated

September 8, 2026

Built-in Types

Every value at the desk is an object of some class. The boring default is to look with type, convert on purpose with int / str / float, and never hope Python will guess.

Mental model

A value is an object in memory. A name is a label stuck on that object. type(x) returns the class of whatever x currently points at. id(x) is an integer that identifies that object for the life of the process. Use id to see whether two names point at the same object, not whether they look equal.

Built-ins you will use every day:

Type What it is at the desk
int counts, ticket ids, prices in cents
float measurements (not money)
bool True / False
str labels, names, status words
NoneType “not set” — one object, spelled None

bool is a subclass of int: True behaves like 1 and False like 0 if you let it. Do not let it. Treat a bool as yes/no.

Conversion is a function call: int("12"), str(7), float("3.5"), bool(0). A failed conversion raises ValueError. That is better than silent garbage.

Worked examples

Case 1: Look at a ticket

Save as ticket_types.py. Print the type of each field so you can see what you actually stored.

# ticket_types.py
def main():
    ticket = {
        "id": 7,
        "table": 12,
        "paid": False,
        "note": "window",
        "closed_at": None,
    }
    for key in ticket:
        value = ticket[key]
        print(key, type(value), value)


if __name__ == "__main__":
    main()

Run:

uv run python ticket_types.py

Output:

id <class 'int'> 7
table <class 'int'> 12
paid <class 'bool'> False
note <class 'str'> window
closed_at <class 'NoneType'> None

None is not the string "None" and not False. It is its own type, with one value.

Case 2: Convert on purpose

The kitchen sends table numbers as text. Prices arrive as strings too. Convert before you add.

# convert_order.py
def main():
    table_text = "12"
    cents_text = "1850"
    table = int(table_text)
    cents = int(cents_text)
    print(type(table_text), type(table))
    print(f"table {table}: {cents} cents")
    print(str(cents) + "c")
    print(float(cents) / 100)


if __name__ == "__main__":
    main()

Run:

uv run python convert_order.py

Output:

<class 'str'> <class 'int'>
table 12: 1850 cents
1850c
18.5

int("12") is a new object. The original string is unchanged. str(cents) + "c" only works because both sides are strings — adding an int to a str raises TypeError.

Case 3: Equality is not identity

== asks “do these look the same?” id asks “are these the same object?” Two lists with the same contents are equal and still two objects.

# same_object.py
def main():
    a = [7, 12]
    b = a
    c = [7, 12]
    print("a == b", a == b)
    print("a is b", a is b)
    print("a == c", a == c)
    print("a is c", a is c)
    print("same id a,b", id(a) == id(b))
    print("same id a,c", id(a) == id(c))


if __name__ == "__main__":
    main()

Run:

uv run python same_object.py

Output:

a == b True
a is b True
a == c True
a is c False
same id a,b True
same id a,c False

b = a does not copy the list. It sticks a second name on the same list. id numbers themselves change every run; comparing them is the useful bit. Use is for None. Use == for values.

Case 4: bool is not a number you should add

# bool_is_int.py
def main():
    paid = True
    print(type(paid), paid)
    print(paid == 1)
    print(paid + 2)
    print(True + True)


if __name__ == "__main__":
    main()

Run:

uv run python bool_is_int.py

Output:

<class 'bool'> True
True
3
2

The program is legal. Adding True to a count is still a bug. Keep bools in if tests and in fields named like paid.

The trap

Python will convert in a few places without asking — if ticket["note"]: treats "" as false, and int(True) is 1. It will not convert "12" + 1. People then reach for implicit tricks (paid + 1) or for id as a substitute for ==.

Save as bad_add.py:

# bad_add.py
def main():
    table = "12"
    print(table + 1)


if __name__ == "__main__":
    main()

Run:

uv run python bad_add.py

Output (the process exits non-zero):

Traceback (most recent call last):
  File "bad_add.py", line 8, in <module>
    main()
  File "bad_add.py", line 4, in main
    print(table + 1)
TypeError: can only concatenate str (not "int") to str

The fix is int(table) + 1 or table + str(1), chosen on purpose. Read the traceback from the bottom.

The boring rule

  • Inspect with type when a value surprises you.
  • Convert with int, str, float, bool at the boundary (input, file, kitchen ticket).
  • Store money as int cents. Use float for measurements, not for prices.
  • Compare values with ==. Compare to None with is.
  • Do not add bools. Do not use id as a hash you print in logs.

Try this

  1. In convert_order.py, feed cents_text = "18.50" and catch ValueError. Print a clear message. Then parse it with float and convert to cents with round.
  2. In ticket_types.py, add a covers field as the string "4". Convert it to int before you print.
  3. In same_object.py, append 99 to b and print a and c. Notice which list changed.