AlgoMaster Logo

Data Types

High Priority16 min readUpdated June 6, 2026
Listen to this chapter
Unlock Audio

Python ships with a small set of built-in types that cover most of what you'll write day to day: numbers, text, true/false flags, sequences, mappings, sets, and the empty value None. This lesson is a map. We'll see each type once, look at how to inspect a value's type at runtime, and group them by mutability and category.

What "Type" Means in Python

Every value in Python is an object, and every object has a type. The type tells Python what the value is, what operations it supports, and how it should behave when used in expressions. The type belongs to the value, not the name. A name can be rebound to any type.

You can inspect a value's type at runtime with the built-in type() function:

The result is the class object itself. For everyday work, the part you read is the class name: int, float, str, and so on. We'll use type() throughout this lesson to confirm what each literal produces.

When Python reads a literal in your source, it builds an object with two key parts: its type and its value. The type drives what +, len(), indexing, and any other operation will actually do.

The Built-in Type Map

Here's the full set of types this lesson covers, grouped by what they're for. Each row links forward to the section in this course that owns the deep dive.

TypeCategoryMutable?Example literalDeep dive
intNumericNo42Numeric Types
floatNumericNo3.14Numeric Types
complexNumericNo2 + 3jNumeric Types
boolNumeric (sub-type of int)NoTrue, FalseBoolean Type
strSequence (text)No"Aisha"Strings section
bytesSequence (binary)Nob"order"Strings section (intro), file I/O
listSequence (general)Yes[1, 2, 3]Lists section
tupleSequence (general)No(1, 2, 3)Tuples section
dictMappingYes{"name": "Aisha"}Dictionaries section
setSetYes{1, 2, 3}Sets section
frozensetSetNofrozenset({1, 2, 3})Sets section
NoneTypeSingletonNoNoneNone Type lesson

That's twelve types worth knowing on day one. There are more in the standard library (decimals, fractions, dates, paths, queues), but everything in the table above is available without an import.

A short tour of each, with just enough code to recognize them.

Numeric Types

Python has three built-in numeric types: integers, floating-point numbers, and complex numbers. Each handles a different shape of number.

A few things worth noting up front. Python integers have arbitrary precision, which means there's no maximum value other than your machine's memory. Floats follow the IEEE 754 double-precision standard, the same one used by most other languages, so 0.1 + 0.2 is the classic 0.30000000000000004. The complex type is for math and engineering work and rarely shows up in business code.

The Boolean type bool is technically a subclass of int. True behaves like 1 and False behaves like 0 in arithmetic. Here's the proof:

The Numeric Types lesson covers int, float, and complex in depth, including precision, division operators, and when to reach for the decimal module instead of float.

Strings and Bytes

Text in Python is stored in str objects. A string is a sequence of Unicode characters, written with single or double quotes. Both work the same way.

Strings are immutable. You can't change a character in place. Operations that look like edits (replacing a substring, uppercasing, slicing) all return a new string.

The bytes type is for raw binary data: file contents, network packets, image bytes. It looks like a string with a b prefix on the literal.

Indexing a bytes object returns an integer (the byte's numeric value), not a one-character bytes object. This trips people up coming from Python 2. You usually create bytes by reading files in binary mode or by encoding a string with .encode().

Sequences: List and Tuple

Sequences hold an ordered collection of values. Python has two general-purpose sequence types: list for mutable sequences, tuple for immutable ones. (Strings and bytes are also sequences, but they're specialized for text and binary data.)

A list uses square brackets:

You can add to a list, remove from it, sort it, and modify items in place. Lists are the workhorse of Python. Anytime you have "a bunch of things in order that might change", you reach for a list.

A tuple uses parentheses (or none at all, since the commas do the real work):

Tuples are immutable. Once created, you can't add, remove, or swap items. They're typically used for fixed-shape records (like a coordinate pair or an order's (id, status, total) snapshot), or as keys in a dictionary (which requires immutability).

The picture is: ordered collections, with three flavors based on what they store and whether they can change after creation.

Mappings: Dict

A dictionary stores key-value pairs. You look up a value by its key, not by an integer position. Keys can be any hashable type (most often strings or numbers); values can be anything.

Dictionaries are mutable. You can add, remove, and update entries:

Since Python 3.7, dictionaries preserve insertion order. You'll see them used everywhere: configuration, JSON-shaped data, lookups by id, counting things. They support O(1) average lookup, default values, and counter-style patterns.

Sets and Frozensets

A set is an unordered collection of unique values. Sets are useful when you care about membership ("is this email in our list?") or want to remove duplicates from a sequence.

Adding "electronics" a second time did nothing because the value was already present. Sets de-duplicate by definition.

A frozenset is the immutable cousin. Once created, it can't change. You'd use one as a dictionary key, or as a value you want to guarantee won't be mutated.

Sets support operations like union, intersection, and difference, and they're the right choice when you need fast membership checks or want to deduplicate items without preserving order.

None and NoneType

None is Python's "nothing" value. It has its own type, NoneType, and there's exactly one None object in any running program. You use it to represent "no result yet", "no value was provided", or "this function doesn't return anything meaningful".

Two things to know now. First, you check for None with is None, not == None. Second, functions that don't have a return statement implicitly return None.

That's why you sometimes see None printed when you call a function expecting a result. The function didn't return anything explicitly, so Python returned None.

Mutable vs Immutable

Whether a type is mutable or immutable changes how you reason about shared references and copying. Here's the summary you'll come back to:

MutableImmutable
listint
dictfloat
setcomplex
bytearray (not covered yet)bool
str
bytes
tuple (with a caveat below)
frozenset
NoneType

Mutable means the object's contents can change after creation. Two names pointing at the same mutable object will both see changes made through either name. Immutable means the object never changes; any "modification" returns a new object instead.

The list was modified in place. The string wasn't, upper() returned a new string and left the original alone.

A subtle point about tuples: they're immutable in the sense that you can't add, remove, or replace their elements. But if a tuple contains a mutable object, that inner object can still be mutated. The tuple's slots still point to the same objects, but those objects can change.

We didn't change which list the tuple contains. We changed the contents of that list. Tuples freeze their slot bindings, not the objects they reference.

Sequence, Mapping, Set: The Three Container Families

Beyond mutable vs immutable, Python organizes container types into three abstract categories. Knowing which category a type belongs to tells you what kinds of operations work on it.

CategoryWhat it isBuilt-in typesCommon operations
SequenceOrdered, indexed by integerstr, bytes, list, tuple, ranges[0], len(s), s + t, for x in s
MappingKey-value pairs, indexed by keydictd[key], d.keys(), d.values(), for k in d
SetUnordered, unique elementsset, frozensetx in s, s | t, s & t, for x in s

The same operator can mean different things in different categories. + concatenates two sequences ([1, 2] + [3, 4] gives [1, 2, 3, 4]) but isn't defined for sets (use | for union instead). Indexing with [] works for sequences (by position) and mappings (by key), but not for sets.

Most of the time you don't need to think about these categories explicitly. You'll learn which type to reach for based on the shape of your data: ordered things go in a list, lookups by key go in a dict, set-like things go in a set. The categories matter when you read documentation that says "any iterable" or "any mapping" and you need to know what fits.

Using type() and isinstance()

type() returns the exact class of an object. isinstance() checks whether an object is of a given class or a subclass of it. For Boolean values, this difference matters.

type(True) is bool, not int, so the first check is False. But bool is a subclass of int, so isinstance(True, int) returns True. In practice, prefer isinstance() for type checks because it respects inheritance and accepts a tuple of types:

This is the idiomatic way to ask "is this any kind of number?" Note that isinstance(value, (int, float, complex)) would return True for bool too, since bool is a subclass of int. If you specifically want to exclude booleans, you have to check for that separately.

Quiz

Data Types Quiz

10 quizzes