Type Hints Python
Type Hints (anotasi tipe) adalah fitur Python yang memungkinkan Anda menentukan tipe data yang diharapkan untuk variabel, parameter fungsi, dan nilai kembalian. Diperkenalkan di Python 3.5, type hints menjadi semakin penting untuk pengembangan Python modern.
Mengapa Menggunakan Type Hints?
Type hints memberikan banyak keuntungan:
- Dokumentasi yang lebih baik - Kode menjadi self-documenting
- Error detection - IDE dan tools dapat mendeteksi bug sebelum runtime
- Autocomplete lebih akurat - IDE bisa memberikan saran yang lebih baik
- Maintainability - Memudahkan pemahaman kode oleh developer lain
- Refactoring lebih aman - Perubahan kode lebih mudah divalidasi
Penting: Type hints di Python bersifat opsional dan tidak mempengaruhi runtime. Python tetap dynamically typed.
Sintaks Dasar
# Anotasi variabel
nama: str = "Budi"
umur: int = 25
tinggi: float = 175.5
aktif: bool = True
# Anotasi parameter dan return type fungsi
def sapa(nama: str) -> str:
return f"Halo, {nama}!"
def tambah(a: int, b: int) -> int:
return a + b
# Fungsi tanpa return value
def cetak_info(pesan: str) -> None:
print(pesan)
Tipe Data Dasar
# Tipe primitif
x: int = 10
y: float = 3.14
z: str = "hello"
flag: bool = True
data: bytes = b"hello"
# None type
result: None = None
Collection Types
Untuk tipe koleksi, gunakan modul typing (Python < 3.9) atau built-in types (Python 3.9+):
# Python 3.9+ (recommended)
angka: list[int] = [1, 2, 3]
nama_umur: dict[str, int] = {"Andi": 25, "Budi": 30}
koordinat: tuple[float, float] = (3.14, 2.71)
unik: set[str] = {"apel", "jeruk"}
# Python 3.5 - 3.8 (gunakan typing)
from typing import List, Dict, Tuple, Set
angka: List[int] = [1, 2, 3]
nama_umur: Dict[str, int] = {"Andi": 25}
koordinat: Tuple[float, float] = (3.14, 2.71)
unik: Set[str] = {"apel", "jeruk"}
Optional dan Union
Untuk nilai yang bisa None atau multiple types:
from typing import Optional, Union
# Optional - bisa None atau tipe tertentu
def cari_user(id: int) -> Optional[str]:
if id == 1:
return "Andi"
return None
# Union - bisa salah satu dari beberapa tipe
def proses(data: Union[str, int]) -> str:
return str(data)
# Python 3.10+ syntax (recommended)
def cari_user(id: int) -> str | None:
if id == 1:
return "Andi"
return None
def proses(data: str | int) -> str:
return str(data)
Callable (Fungsi sebagai Parameter)
from typing import Callable
# Fungsi yang menerima fungsi lain sebagai parameter
def apply_twice(func: Callable[[int], int], value: int) -> int:
return func(func(value))
def double(x: int) -> int:
return x * 2
result = apply_twice(double, 5) # 20
# Callable dengan multiple arguments
def operasi(func: Callable[[int, int], int], a: int, b: int) -> int:
return func(a, b)
Any Type
Ketika tipe bisa apa saja:
from typing import Any
def proses_apapun(data: Any) -> Any:
return data
Type Aliases
Buat alias untuk tipe yang kompleks:
from typing import TypeAlias
# Type alias
UserId: TypeAlias = int
UserData: TypeAlias = dict[str, str | int]
def get_user(user_id: UserId) -> UserData:
return {"nama": "Andi", "umur": 25}
# Untuk tipe yang lebih kompleks
Matrix: TypeAlias = list[list[float]]
def transpose(matrix: Matrix) -> Matrix:
return [[row[i] for row in matrix] for i in range(len(matrix[0]))]
Generic Types
Untuk fungsi yang bekerja dengan berbagai tipe:
from typing import TypeVar
T = TypeVar('T')
def first_element(items: list[T]) -> T:
return items[0]
# Bisa digunakan dengan list tipe apapun
angka = first_element([1, 2, 3]) # int
kata = first_element(["a", "b", "c"]) # str
Literal Types
Untuk nilai yang harus spesifik:
from typing import Literal
def set_status(status: Literal["active", "inactive", "pending"]) -> None:
print(f"Status: {status}")
set_status("active") # OK
set_status("unknown") # Type error (terdeteksi oleh type checker)
# Berguna untuk opsi terbatas
Mode = Literal["read", "write", "append"]
def open_file(path: str, mode: Mode) -> None:
pass
TypedDict
Untuk dictionary dengan struktur yang tetap:
from typing import TypedDict
class User(TypedDict):
nama: str
umur: int
email: str
def create_user(data: User) -> None:
print(f"Creating user: {data['nama']}")
# Type checker akan memvalidasi struktur
user: User = {
"nama": "Andi",
"umur": 25,
"email": "[email protected]"
}
Anotasi untuk Class
class Mahasiswa:
nama: str
nim: str
ipk: float
def __init__(self, nama: str, nim: str) -> None:
self.nama = nama
self.nim = nim
self.ipk = 0.0
def set_ipk(self, ipk: float) -> None:
self.ipk = ipk
def get_info(self) -> str:
return f"{self.nama} ({self.nim}): IPK {self.ipk}"
Dataclasses dengan Type Hints
from dataclasses import dataclass
@dataclass
class Produk:
nama: str
harga: float
stok: int = 0
def total_nilai(self) -> float:
return self.harga * self.stok
produk = Produk("Laptop", 15000000, 10)
print(produk.total_nilai()) # 150000000
Tools untuk Type Checking
Type hints tidak diperiksa saat runtime. Gunakan tools berikut:
1. mypy
pip install mypy
mypy script.py
2. pyright (VS Code Pylance)
Sudah terintegrasi dengan VS Code melalui extension Pylance.
3. pytype (Google)
pip install pytype
pytype script.py
Contoh Lengkap
from dataclasses import dataclass
from typing import Optional
@dataclass
class Alamat:
jalan: str
kota: str
kode_pos: str
@dataclass
class Karyawan:
nama: str
email: str
gaji: float
alamat: Optional[Alamat] = None
def info_lengkap(self) -> str:
info = f"{self.nama} - {self.email}"
if self.alamat:
info += f" ({self.alamat.kota})"
return info
def hitung_total_gaji(karyawan_list: list[Karyawan]) -> float:
return sum(k.gaji for k in karyawan_list)
def cari_karyawan(
karyawan_list: list[Karyawan],
nama: str
) -> Karyawan | None:
for k in karyawan_list:
if k.nama.lower() == nama.lower():
return k
return None
# Penggunaan
alamat = Alamat("Jl. Sudirman", "Jakarta", "12190")
k1 = Karyawan("Andi", "[email protected]", 10000000, alamat)
k2 = Karyawan("Budi", "[email protected]", 12000000)
semua = [k1, k2]
print(hitung_total_gaji(semua)) # 22000000