🐍 Python Course · Stage 4 · Lesson 60 of 89 · Concept: Data Types
Course Overview →

🟩 These concept pages connect Python to programming in general. Read Beginner tab first.

← Concept: Variables Concept: Operators →
thecodex.expert  ·  The Codex Family of Knowledge
CS Concepts

Data Types

The type of a value determines what you can do with it — and how the computer stores it.

CS Concepts Requires: Variables ~16 min read Last verified:
Canonical Definition

A data type is a classification that specifies what kind of value a variable can hold, what operations are valid on that value, and how the value is represented in memory — determining both the range of expressible values and the set of applicable operations.

🟩 Beginner

What types are and why every language has them

What you'll learn: The primitive types (integer, float, boolean, string) that exist in almost every language. Composite types that group values together. Why types matter — preventing bugs and determining how memory is used.

How to read this tab: Compare the type tables on this page with Python's specific types in Variables & Types. The concepts here explain the why; the Python page shows the how.

⏱ 20 min 📄 3 sections 🔶 Prerequisite: Variables concept
One sentence that captures it

A data type is a label that tells the program what kind of thing a value is — so it knows what operations make sense and how much memory to reserve.

Four universals: integers (whole numbers), floats (decimal numbers), booleans (true/false), and strings (text). Almost every language has these. The differences are in the details: Python integers have no size limit; C integers overflow. Python strings are Unicode; C strings are byte arrays. Knowing the common primitives means learning any new language's type system is mostly recognising familiar things.

The primitive types every language has

Every general-purpose programming language has a small set of primitive types — the fundamental building blocks from which all other data is constructed:

  • Integer — whole numbers. 42, -7, 0. Used for counting, indexing, and anything that shouldn't have a fractional part.
  • Float — numbers with a decimal point. 3.14, -0.001. Stored in binary floating point (IEEE 754). Approximate, not exact.
  • Boolean — two values only: true or false. The result of every comparison.
  • Character / String — text. A single character ('A') or a sequence of characters ("Hello").
Pythontypes.py
age = 28            # int
price = 1299.99     # float
is_member = True    # bool
name = "Priya"      # str

print(type(age))    # <class 'int'>
print(type(price))  # <class 'float'>

# Operations depend on type
print(age + 2)      # 30  — integer addition
print(name + "!")   # "Priya!"  — string concatenation
print(age + name)   # TypeError — can't add int and str
💡

The universal containers: arrays/lists (ordered by index), dictionaries/maps (key-value pairs), tuples (fixed ordered groups), sets (unordered unique values). Python has all four as built-ins. Other languages may require importing them from a library. The same concepts appear everywhere — just different names and syntax.

Composite types: collections of values

Languages also provide types that hold multiple values: arrays (ordered sequences), dictionaries / maps (key-value pairs), tuples (fixed-size ordered collections), and structs / records (named fields of different types). These are built from primitive types.

💡

Types serve two purposes: correctness and performance. Correctness: if a function expects an integer and receives a string, a type error is better than wrong results. Performance: a statically-typed compiler knows exactly how many bytes each variable needs and can optimise accordingly. Python trades the performance benefit for flexibility — that's the explicit design choice.

Why types matter

Types prevent mistakes. If you try to divide a name by a number, the type system either catches it at compile time (static typing — Java, Rust, C) and refuses to run the program, or catches it at runtime (dynamic typing — Python, JavaScript) and raises an error. Without types, the computer would just do the operation on the raw bits — producing garbage results silently.

📎

In Python, you don't manage this — but it happens. A C int is 4 bytes. A C long is 8 bytes. A Python int is a heap-allocated object with no size limit — but it uses more memory than a C int. This is why NumPy (which uses C-style typed arrays) is dramatically faster for numerical computation than plain Python lists.

How types determine memory size

An int in Java is always 32 bits — exactly 4 bytes. A long is 64 bits. A boolean is 1 bit of information but typically stored in 1 byte. Knowing the size lets the compiler allocate exactly the right amount of memory and ensures that operations on values of the same type use the same machine instructions.

🔵 Intermediate

Type systems — static vs dynamic, strong vs weak

What you'll learn: Static vs dynamic typing (when types are checked). Strong vs weak typing (whether coercion happens silently). How Python, JavaScript, Java, Go, and Rust each fit on these axes. Type coercion and conversion.

How to read this tab: The 2×2 grid of static/dynamic × strong/weak is the key framework. Place Python, JavaScript, C, and Java on that grid and the differences between languages immediately become clearer.

⏱ 20 min 📄 2 sections 🔶 Prerequisite: Beginner tab
📎

Boolean is a subtype of integer in Python. True is 1, False is 0. This is why True + True == 2 works in Python. Most other languages keep booleans completely separate from integers. Python's choice is historically motivated (Python predates the bool type) and occasionally surprising.

Primitive types in detail

TypePythonJavaC (typical 64-bit)Rust
Integer (32-bit signed)int (arbitrary)intinti32
Integer (64-bit signed)int (arbitrary)longlong longi64
Float (64-bit)floatdoubledoublef64
Booleanboolboolean_Bool (C99)bool
Unicode characterstr (len 1)char (UTF-16)char (byte)char (Unicode scalar)

Python is strongly typed — it will NOT coerce silently. "5" + 3 raises TypeError in Python. In JavaScript it returns "53". In C it's undefined behaviour. Python requires you to be explicit: int("5") + 3 == 8. This makes Python programs more predictable at the cost of slightly more verbose code.

Type coercion and conversion

Implicit coercion: the language automatically converts one type to another in certain contexts. JavaScript: "5" * 210 (string coerced to number). C: assigning a double to an int silently truncates the decimal. Explicit conversion: the programmer requests a conversion. Python: int("42")42. Java: (int) 3.73.

📎

Python objects have metadata overhead. A Python integer doesn't just store the integer value — it stores a reference count, a type pointer, and the actual value. A Python int for the number 1 uses ~28 bytes. A C int uses 4 bytes. This overhead is why Python is slower than C for numeric-heavy code and why NumPy matters.

Memory representation

A 32-bit integer uses 4 bytes in two's complement. A 64-bit float uses 8 bytes in IEEE 754 double precision (1 sign + 11 exponent + 52 mantissa bits). A Python string (CPython) is a Unicode object stored as a contiguous array of code points — 1, 2, or 4 bytes per character depending on the highest code point in the string (PEP 393 compact encoding). A Python integer object has a minimum overhead of 28 bytes for small values — significantly more than C's 4 bytes, because Python integers carry type tags, reference counts, and support arbitrary precision.

Commonly confused
A float is not an exact decimal number. 0.1 in float64 is stored as approximately 0.1000000000000000055511151231257827021181583404541015625. This is the mathematically correct IEEE 754 representation, not an error.
Python's int is not a 32-bit or 64-bit integer. Python integers have arbitrary precision — they grow as large as needed. The price is memory overhead: a small Python int object uses 28 bytes versus 4 bytes for a C int.
A char in Java is not a byte. Java char is 16 bits (UTF-16 code unit), not 8 bits. Characters outside the Basic Multilingual Plane (emoji, many CJK characters) require two Java char values (a surrogate pair).
🔴 Expert

Memory representation, IEEE 754, and type theory foundations

What you'll learn: How different types map to memory layouts. IEEE 754 floating point representation and why 0.1 + 0.2 ≠ 0.3. Type theory foundations — nominal vs structural typing.

How to read this tab: Read when you need to understand floating point precision bugs or when studying type systems formally.

⏱ 20 min 📄 3 sections 🔶 Prerequisite: After Stage 2
📎

Nominal vs structural typing. Nominal typing (Java, C#): two types are compatible only if they have an explicit inheritance or implementation relationship. Structural typing (TypeScript, Python Protocols): two types are compatible if they have the same methods/attributes. Python uses nominal typing by default but adds structural typing through Protocols (PEP 544).

Type theory foundation

In type theory, a type is formally a set of values together with a collection of operations defined on those values. The type system assigns a type to every expression and uses this to prove statically (or check dynamically) that operations are applied to values of compatible types. This is the type safety property: a well-typed program cannot get stuck in an undefined state (Pierce, Types and Programming Languages, 2002).

IEEE 754 float internals

Double precision (binary64): 1 sign bit, 11 exponent bits (biased by 1023), 52 mantissa bits. Value: (−1)s × 2e−1023 × 1.f. The integer 253 + 1 = 9,007,199,254,740,993 cannot be represented exactly in float64 — this is why JavaScript numbers (all float64) produce 9007199254740992 + 1 === 9007199254740992.

Specification reference

IEEE Std 754-2019. IEEE Standard for Floating-Point Arithmetic. IEEE. — Authoritative floating-point specification. ISO/IEC 9899:2018 (ISO C17) §6.2.5. — Formal C type specifications. Pierce, B. C. (2002). Types and Programming Languages. MIT Press.

How this connects
Formal basis
Source confidence: High Last verified: Primary source: IEEE Std 754-2019 · ISO C17 §6.2.5

✅ Expert tab complete

  • I know why 0.1 + 0.2 is not exactly 0.3 in any IEEE 754 language
  • I understand the difference between nominal typing (Java) and structural typing (TypeScript/Python Protocols)

Continue to Operators →

Sources

1
IEEE Std 754-2019. IEEE Standard for Floating-Point Arithmetic. IEEE Computer Society. — Authoritative specification for floating-point types.
2
ISO/IEC 9899:2018 (ISO C17). §6.2.5 — Types. International Organization for Standardization. — Formal C type specifications, ranges, and representations.
3
Pierce, B. C. (2002). Types and Programming Languages. MIT Press. — Formal type theory; type safety and type systems.
4
Python Software Foundation. PEP 393 — Flexible String Representation. peps.python.org/pep-0393/. — Python's compact string encoding, determining character storage size.