Learning Python - Advanced Data Types & Collections
Episode 5 of 23

Learning Python - Advanced Data Types & Collections

This episode deepens Python's collection data types: the collections module with deque, defaultdict, Counter, and namedtuple, plus the basics of typing for type annotations. You'll also learn memory and performance considerations when choosing data structures.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

We already know list, dict, set, and tuple. But Python has the collections module that provides specialized versions with better behavior and performance for specific cases. Episode 5 covers them one by one.

We also start touching typing — type annotations that are becoming increasingly important in modern Python and that we'll deepen in episode 17. Finally, we discuss memory and performance considerations so you can choose the right data structure.

The collections Module

deque: A Two-Way Queue

deque is a double-ended queue with O(1) append and pop operations at both ends:

PythonMenggunakan deque
from collections import deque
 
antrian = deque(["a", "b", "c"])
antrian.append("d")
antrian.appendleft("z")
print(antrian)
 
item = antrian.popleft()
print(item)
print(antrian)

deque(["a", "b", "c"]) creates a double-ended queue. Unlike a list, whose insert(0, ...) is slow, deque.appendleft and popleft are always fast. deque is a great fit for queues, buffers, and sliding windows.

defaultdict: Automatic Defaults

defaultdict provides automatic default values when a key doesn't exist, removing the boilerplate of checking:

PythonMenggunakan defaultdict
from collections import defaultdict
 
jumlah = defaultdict(int)
kata = ["a", "b", "a", "c", "a"]
 
for k in kata:
    jumlah[k] += 1
 
print(dict(jumlah))
print(jumlah["tidak_ada"])

defaultdict(int) creates a dict that calls int() when a key isn't found, so jumlah[k] += 1 works directly without checks. Other variants can use list, set, or a custom function.

Counter: Counting Occurrences

Counter is a specialized dict for counting element occurrences:

PythonMenggunakan Counter
from collections import Counter
 
kata = ["apel", "jeruk", "apel", "mangga", "apel"]
hitung = Counter(kata)
 
print(hitung)
print(hitung.most_common(2))

Counter(kata) counts the frequency of each element. hitung.most_common(2) returns the two most frequent elements. Counter supports arithmetic operations like adding and subtracting between Counters.

namedtuple: Named Tuples

namedtuple creates a tuple whose fields can be accessed by name:

PythonMenggunakan namedtuple
from collections import namedtuple
 
Titik = namedtuple("Titik", ["x", "y"])
t = Titik(3, 4)
 
print(t.x)
print(t.y)
print(t[0])

namedtuple("Titik", ["x", "y"]) creates a tuple class with named fields. t.x and t[0] return the same value. namedtuple makes code more descriptive while staying as memory-efficient as a tuple.

typing Basics

Simple Type Annotations

The typing module provides generic types for annotations. Annotations make code clearer and can be checked by mypy:

PythonAnotasi tipe dasar
from typing import List, Dict, Optional
 
def rata_rata(angka: List[float]) -> float:
    return sum(angka) / len(angka)
 
def cari_nama(data: Dict[str, str], kunci: str) -> Optional[str]:
    return data.get(kunci)
 
print(rata_rata([1.0, 2.0, 3.0]))
print(cari_nama({"a": "Arman"}, "a"))

List[float] declares a list of floats, Dict[str, str] maps strings to strings, and Optional[str] can hold a string or None. Annotations don't affect runtime, but they serve as documentation and input for mypy validation in episode 17.

Union and More Complex Types

For more complex cases, Python 3.10 and above provide the X | Y syntax:

PythonUnion dengan pipe
from typing import Union
 
def tampilkan(nilai: Union[int, str]) -> str:
    return str(nilai)
 
def tampilkan_py310(nilai: int | str) -> str:
    return str(nilai)
 
print(tampilkan(10))
print(tampilkan_py310("halo"))

int | str in Python 3.10 replaces Union[int, str]. This pipe syntax is more concise and has become the standard in modern code. We'll cover Annotated, TypedDict, Protocol, and ParamSpec in episode 17.

Memory and Performance of Data Structures

Comparing Collections

Every data structure has memory and speed trade-offs:

  • list: dynamic sequence, fast index access, slow linear search.
  • tuple: like a list but immutable and more memory-efficient.
  • dict: fast O(1) key lookup, but memory-hungry.
  • set: fast O(1) membership, unique elements without order.
  • deque: fast operations at both ends, ideal for queues.

A Practical Comparison Example

Let's compare the lookup speed of a list and a set with a large dataset:

PythonPerbandingan list vs set
import time
 
data = list(range(100_000))
target = 99_999
 
mulai = time.perf_counter()
ada_list = target in data
lama_list = time.perf_counter() - mulai
 
himpunan = set(data)
mulai = time.perf_counter()
ada_set = target in himpunan
lama_set = time.perf_counter() - mulai
 
print(ada_list, lama_list)
print(ada_set, lama_set)

target in himpunan uses a hash table so the lookup is nearly instant, while target in data on a list scans linearly. For repeated membership checks, a set always wins.

Closing

Key takeaways:

  • deque provides O(1) operations at both ends for queues.
  • defaultdict provides automatic default values when a key is missing.
  • Counter counts element occurrences easily.
  • namedtuple names tuple fields without losing efficiency.
  • typing provides type annotations checked by mypy.
  • Choose data structures based on memory and speed trade-offs.

In the next episode, episode 6, we'll cover exception handling and resource management — try, except, else, and finally, creating custom exceptions, context managers with the with keyword, and contextlib for building your own context managers. These are essential skills to make your programs resilient to errors!

Learning Python - Advanced Data Types & Collections | Learn Python