Anotasi nama: str menggambarkan satu nilai, tetapi data nyata hampir selalu bergerak dalam koleksi: daftar harga, kamus stok, himpunan tag. Anotasi list saja tidak menjawab pertanyaan terpenting — berisi apa list tersebut? Satu tipe koleksi bisa menampung isi apa pun, jadi tipe koleksi perlu parameter: satu tipe lagi yang mendeskripsikan setiap elemennya. Kita mulai dari empat generic type bawaan yang menutup 90% kebutuhan sehari-hari.
Empat Generik Bawaan yang Paling Sering Dipakai #
Sejak Python 3.9, tipe bawaan bisa langsung diparameterisasi dengan tanda kurung siku:
| Anotasi | Arti | Contoh isi sah |
|---|---|---|
list[int] | list yang setiap elemennya int | [5000, 7500] |
dict[str, int] | dictionary key str, value int | {"kopi": 12} |
tuple[int, int] | tuple tetap dua elemen int | (-6, 121) |
set[str] | set yang setiap elemennya str | {"promo", "baru"} |
Mari kita lihat keempatnya bekerja dalam satu program:
harga: list[int] = [5000, 7500, 12000]
stok: dict[str, int] = {"kopi": 12, "teh": 8}
koordinat: tuple[int, int] = (-6, 121)
tags: set[str] = {"promo", "baru"}
print(harga)
print(stok)
print(koordinat)
print(sorted(tags))Output yang Dihasilkan:
[5000, 7500, 12000]
{'kopi': 12, 'teh': 8}
(-6, 121)
['baru', 'promo']Mari kita telaah baris-barisnya:
- Baris 1 (
harga: list[int] = ...): variabelhargadianotasi sebagai list of integer; checker kini akan menolak bila kita menambahkan string ke dalamnya. - Baris 2 (
stok: dict[str, int] = ...): dua parameter generik terbaca berurutan — key bertipestr, value bertipeint. - Baris 3 (
koordinat: tuple[int, int]): tuple dengan jumlah elemen tetap; setiap posisi mendapatkan tipe masing-masing, dan jumlahnya dihitung. - Baris 4 (
tags: set[str] = ...): himpunan string; kita mencetaksorted(tags)karena urutan iterasisetbisa berbeda-beda,sorted()membuat keluaran selalu sama.
tuple yang Panjangnya Bebas #
tuple[int, int] mengunci jumlah elemen — cocok untuk koordinat atau pasangan tetap. Untuk baris data sepanjang apa pun, gunakan ellipsis ...:
def rata_rata(nilai: tuple[int, ...]) -> float:
return sum(nilai) / len(nilai)
print(rata_rata((80, 90, 100)))Output yang Dihasilkan:
90.0Anotasi tuple[int, ...] dibaca “tuple berisi integer, sepanjang apa pun, termasuk kosong”. Bedakan dua bentuk ini dengan cermat: tuple[int, int] berarti tepat dua elemen, sedangkan tuple[int, ...] berarti banyak elemen bertipe sama.
Generik Bersarang dan Signature Function #
Parameter generik bisa diisi tipe generik lain, dan di sinilah anotasi mulai menjelaskan struktur data secara utuh:
def total_per_kategori(kategori: dict[str, list[int]]) -> dict[str, int]:
return {nama: sum(harga) for nama, harga in kategori.items()}
data = {"makanan": [5000, 7500], "minuman": [3000, 4000]}
print(total_per_kategori(data))Output yang Dihasilkan:
{'makanan': 12500, 'minuman': 7000}Signature total_per_kategori kini membaca dirinya sendiri: terima dictionary yang key-nya nama kategori dan value-nya list of harga, lalu kembalikan dictionary nama ke total. Anotasi bersarang dibaca dari dalam ke luar — list[int] adalah tipe value dictionary, dan keseluruhan dict[str, list[int]] adalah tipe parameter. Pembaca signature tidak perlu menebak bentuk data lagi.
Checker Membaca Isi Koleksi #
Anotasi generik baru terasa manfaatnya saat checker menolak kesalahan. Simpan sebagai harga.py:
harga: list[int] = [5000, 7500]
harga.append("kopi")Baris kedua sah-sah saja menurut runtime — list Python menerima tipe apa pun. Namun mypy memahami kontrak list[int]:
python3 -m mypy harga.pyOutput yang Dihasilkan:
harga.py:2: error: Argument 1 to "append" of "list" has incompatible type "str"; expected "int" [arg-type]
Found 1 error in 1 file (checked 1 source file)Checker tahu bahwa method append milik list[int] hanya menerima int — pengetahuan itu diturunkan dari parameter generik yang kita tulis. Tanpa parameter tersebut, anotasi list polos akan membuat checker pasrah dan kesalahan lolos.
Sintaks Lama: typing.List #
Sebelum Python 3.9, tipe bawaan belum bisa diparameterisasi, jadi kita wajib mengimpor bentuk kapital dari module typing:
from typing import Dict, List
harga_lama: List[int] = [5000]
stok_lama: Dict[str, int] = {"kopi": 12}Dua gaya tersebut setara di mata checker, dan bentuk kapital masih ditemui di kode lama maupun dokumentasi lama. Untuk kode baru yang berjalan di Python 3.9 ke atas, PEP 585 dan panduan resmi merekomendasikan bentuk huruf kecil: list[int], bukan List[int] — lebih pendek, tanpa import, dan konsisten dengan syntax pembuatan koleksi itu sendiri.