Tidak semua data layak disimpan di setiap object. Total koleksi perpustakaan, batas maksimal pinjam, lokasi rak penyimpanan — nilai-nilai seperti ini dimiliki bersama oleh seluruh instance. Menyalinnya ke setiap object memboroskan memori dan, lebih buruk, rawan tidak sinkron antar object. Python menyediakan tempat yang tepat untuk data bersama: class attribute, yang ditulis langsung di body class. Chapter ini membahas cara kerjanya, relasinya dengan urutan pencarian attribute, dan satu jebakan terkenal yang wajib dihindari.

Data Bersama di Level Class #

Class attribute ditulis langsung di body class, di luar method apa pun. Statement class dieksekusi sekali saat modul dimuat, dan assignment di body class menempel pada object class itu sendiri. Kegunaan paling umum: penghitung (counter) yang melacak berapa banyak object yang pernah dibuat:

python
class Buku:
    jumlah_buku = 0

    def __init__(self, judul, penulis):
        self.judul = judul
        self.penulis = penulis
        Buku.jumlah_buku += 1

buku1 = Buku("Laskar Pelangi", "Andrea Hirata")
buku2 = Buku("Bumi Manusia", "Pramoedya A. Toer")
buku3 = Buku("Negeri 5 Menara", "A. Fuadi")

print("Total buku terdaftar:", Buku.jumlah_buku)

Output yang Dihasilkan:

text
Total buku terdaftar: 3

Mari kita telaah baris-baris kode di atas:

  1. Baris 2 (jumlah_buku = 0): nilai 0 disimpan sekali pada object class Buku — bukan pada tiap instance.
  2. Baris 7 (Buku.jumlah_buku += 1): setiap kali __init__ berjalan, penghitung di class bertambah satu. Pembaruan dilakukan lewat nama class (Buku.jumlah_buku), bukan lewat self.
  3. Baris 13: setelah tiga object dibuat, nilai bersama di class menjadi 3.

Pembaruan lewat nama class itu penting. Jika kita menulis self.jumlah_buku += 1, Python membaca nilai dari class lalu menulis hasilnya sebagai attribute instance — penghitung di class tidak pernah bertambah, dan tiap object justru membawa salinan angkanya sendiri.

Perubahan di Class Terlihat oleh Semua Instance #

Pada Chapter Instance Attributes kita melihat bahwa pencarian attribute berhenti di instance jika ditemukan; jika tidak, pencarian jatuh ke class. Konsekuensinya: mengubah class attribute langsung mengubah hasil pembacaan di semua instance yang tidak menimpanya:

python
class Buku:
    lokasi_rak = "Rak A"

    def __init__(self, judul):
        self.judul = judul

buku1 = Buku("Laskar Pelangi")
buku2 = Buku("Bumi Manusia")

print(buku1.lokasi_rak)
print(buku2.lokasi_rak)

Buku.lokasi_rak = "Rak B"

print(buku1.lokasi_rak)
print(buku2.lokasi_rak)

Output yang Dihasilkan:

text
Rak A
Rak A
Rak B
Rak B

Kedua object awalnya sama-sama membaca "Rak A" lewat mekanisme fallback ke class. Begitu Buku.lokasi_rak diubah menjadi "Rak B", kedua pembacaan langsung ikut berubah — tanpa satu pun object menyimpan datanya sendiri. Inilah perilaku “data bersama” yang dicari dari class attribute.

Jebakan Mutable Class Attribute #

Perhatikan dua perpustakaan berikut yang seharusnya punya daftar genre masing-masing:

python
class Perpustakaan:
    daftar_genre = []

    def __init__(self, nama):
        self.nama = nama

    def tambah_genre(self, genre):
        self.daftar_genre.append(genre)

perpus_kota = Perpustakaan("Perpustakaan Kota")
perpus_sekolah = Perpustakaan("Perpustakaan Sekolah")

perpus_kota.tambah_genre("Fiksi")
perpus_sekolah.tambah_genre("Biografi")

print("Genre Perpustakaan Kota:", perpus_kota.daftar_genre)
print("Genre Perpustakaan Sekolah:", perpus_sekolah.daftar_genre)

Output yang Dihasilkan:

text
Genre Perpustakaan Kota: ['Fiksi', 'Biografi']
Genre Perpustakaan Sekolah: ['Fiksi', 'Biografi']

Kedua perpustakaan menampilkan isi yang sama persis. Mari kita bedah penyebabnya:

  1. Baris 2 (daftar_genre = []): satu object list dibuat dan disimpan di class.
  2. Baris 8 (self.daftar_genre.append(genre)): pembacaan self.daftar_genre tidak menemukan attribute di instance, jadi pencarian jatuh ke class dan menemukan list bersama. Method .append() lalu memutasi list tersebut di tempat.
  3. Kedua pemanggilan tambah_genre() mengubah list yang sama — genre dari dua perpustakaan bercampur jadi satu.

Perbaikannya: pindahkan pembuatan list ke __init__ agar setiap instance mendapat list sendiri:

python
class Perpustakaan:
    def __init__(self, nama):
        self.nama = nama
        self.daftar_genre = []

    def tambah_genre(self, genre):
        self.daftar_genre.append(genre)

perpus_kota = Perpustakaan("Perpustakaan Kota")
perpus_sekolah = Perpustakaan("Perpustakaan Sekolah")

perpus_kota.tambah_genre("Fiksi")
perpus_sekolah.tambah_genre("Biografi")

print("Genre Perpustakaan Kota:", perpus_kota.daftar_genre)
print("Genre Perpustakaan Sekolah:", perpus_sekolah.daftar_genre)

Output yang Dihasilkan:

text
Genre Perpustakaan Kota: ['Fiksi']
Genre Perpustakaan Sekolah: ['Biografi']

Aturan praktisnya mudah diingat: nilai immutable (angka, string, tuple) aman sebagai class attribute; object mutable (list, dict, set) hampir selalu lebih tepat menjadi instance attribute.

Konstanta di Level Class #

Class attribute juga tempat alami bagi konstanta — nilai tetap yang dipakai bersama dan tidak pernah diubah selama program berjalan. Konvensi Python menuliskannya dengan huruf KAPITAL:

python
class Buku:
    MAKS_PINJAM = 3

    def __init__(self, judul):
        self.judul = judul

    def masih_bisa_dipinjam(self, jumlah_dipinjam):
        return jumlah_dipinjam < Buku.MAKS_PINJAM

buku = Buku("Laskar Pelangi")

print(buku.masih_bisa_dipinjam(2))
print(buku.masih_bisa_dipinjam(3))

Output yang Dihasilkan:

text
True
False

Nilai MAKS_PINJAM tinggal satu tempat: mengubah batas pinjam hanya perlu menyentuh satu baris. Untuk sekumpulan konstanta yang membentuk pilihan tetap (hari, status, kategori), Python menyediakan enum yang lebih terstruktur — dibahas pada chapter Enum di Section Advanced Data Modeling.

Dengan attribute dan datanya beres, saatnya memberi perilaku: Chapter Instance Methods membahas apa yang sebenarnya terjadi ketika sebuah method dipanggil.