Python Data Types — The Complete Guide for 2026

Sanjeev SharmaSanjeev Sharma
5 min read

Advertisement

Introduction

Why This Matters

Every piece of data in Python is an object with a type, and choosing the right type is fundamental to writing correct, efficient code. Python's dynamic typing makes it flexible, but that flexibility comes with responsibility. Misusing types is a leading cause of runtime errors, performance bottlenecks, and subtle bugs.

Understanding Python's type system also unlocks advanced features like type hints, Pydantic validation, dataclasses, and mypy static analysis — all of which are widely used in production Django, FastAPI, and data science codebases. Type awareness is also heavily tested in Python technical interviews.

This guide covers every built-in data type with practical examples, mutability rules, and when to choose one type over another.

Numeric Types: int, float, complex

# int: arbitrary precision
age = 25
large = 10 ** 100  # Python handles big integers natively
 
# float: IEEE 754 double precision
price = 19.99
pi = 3.14159
 
# float precision gotcha
print(0.1 + 0.2)          # 0.30000000000000004
from decimal import Decimal
print(Decimal("0.1") + Decimal("0.2"))  # 0.3 (exact)
 
# complex
z = 3 + 4j
print(z.real, z.imag)  # 3.0 4.0

Strings

Strings are immutable sequences of Unicode characters.

name = "Alice"
greeting = f"Hello, {name}!"  # f-string (Python 3.6+)
 
# Common methods
print("  hello  ".strip())       # 'hello'
print("hello".upper())           # 'HELLO'
print("a,b,c".split(","))        # ['a', 'b', 'c']
print("-".join(["a", "b", "c"])) # 'a-b-c'
print("hello world".replace("world", "Python"))  # 'hello Python'
 
# Multi-line string
message = """
Dear user,
Welcome to our platform.
"""

Boolean

bool is a subclass of intTrue == 1 and False == 0.

is_active = True
is_deleted = False
 
print(True + True)   # 2
print(bool(0))       # False
print(bool(""))      # False
print(bool([]))      # False
print(bool(None))    # False
print(bool("0"))     # True — non-empty string

List — Mutable Ordered Sequence

fruits = ["apple", "banana", "cherry"]
fruits.append("date")
fruits.insert(1, "avocado")
fruits.remove("banana")
fruits.sort()
 
print(fruits[0])       # first element
print(fruits[-1])      # last element
print(fruits[1:3])     # slice
 
# List is mutable
fruits[0] = "apricot"

Tuple — Immutable Ordered Sequence

coordinates = (40.7128, -74.0060)
rgb = (255, 128, 0)
 
# Unpacking
lat, lon = coordinates
print(f"Lat: {lat}, Lon: {lon}")
 
# Tuples as dict keys (lists cannot be keys)
location_map = {(40.7128, -74.0060): "New York"}
 
# Named tuple for readability
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(3, 4)
print(p.x, p.y)  # 3 4

Dictionary — Mutable Key-Value Map

user = {
    "id": 1,
    "name": "Alice",
    "email": "alice@example.com",
}
 
# Access
print(user["name"])
print(user.get("phone", "N/A"))  # safe access with default
 
# Mutate
user["age"] = 30
user.update({"email": "new@example.com", "active": True})
 
# Iterate
for key, value in user.items():
    print(f"{key}: {value}")
 
# Dict comprehension
squared = {x: x**2 for x in range(5)}

Set — Mutable Unordered Unique Collection

tags = {"python", "web", "api", "python"}  # duplicates removed
print(tags)  # {'python', 'web', 'api'}
 
tags.add("fastapi")
tags.discard("web")  # no error if not present
 
# Set operations
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
print(a | b)  # union: {1, 2, 3, 4, 5, 6}
print(a & b)  # intersection: {3, 4}
print(a - b)  # difference: {1, 2}

None

None is Python's null value — a singleton of NoneType.

result = None
 
if result is None:  # use 'is', not '=='
    print("No result yet")
 
def find_user(id: int):
    # Returns None implicitly if not found
    pass

Type Checking and Conversion

print(type(42))       # <class 'int'>
print(isinstance(42, int))   # True
print(isinstance(42, (int, float)))  # True
 
# Conversion
int("42")      # 42
float("3.14")  # 3.14
str(100)       # '100'
list((1,2,3))  # [1, 2, 3]
set([1,1,2])   # {1, 2}

Common Mistakes

  • Using mutable defaults in function signatures: def f(items=[]) — use None instead
  • Comparing to None with == instead of is
  • Confusing shallow copy with deep copy for nested structures
  • Using a list where a set is more appropriate for membership checks
  • Assuming dict ordering in Python 2 — in Python 3.7+, dicts maintain insertion order

Best Practices

  • Use type hints to document expected types: def greet(name: str) -> str
  • Prefer tuples for fixed-size records that should not change
  • Use dataclasses or Pydantic BaseModel for structured data in APIs
  • Use frozenset when you need a hashable, immutable set
  • Use collections.defaultdict or .get() to avoid KeyError in dicts

Key Takeaways

  • Python has 8 core built-in types: int, float, complex, str, bool, list, tuple, dict, set
  • Mutable types (list, dict, set) can be changed in place; immutable types (str, tuple, int) cannot
  • None is Python's null value and should be compared with is, not ==
  • Dicts in Python 3.7+ maintain insertion order
  • Sets are ideal for deduplication and fast membership testing (O(1) lookup)
  • Use isinstance() for type checking, not type() ==
  • Type hints + mypy or Pyright add static type safety to dynamic Python code

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro