Metaclass di Python

Ternyata metaclass di Python itu sangat menarik karena kita bisa melakukan ilmu hitam 😀 Salah satu ilmu hitam yang sedang/akan saya pakai adalah membuat deklarasi kelas yang baru saja dibuat menjadi lenyap secara tiba2 dan alih-alih kita mendapatkan sebuah objek/instance dari kelas tersebut.

Mengapa saya memerlukan sesuatu yang “aneh” seperti ini? Singkatnya saya sedang membuat semacam domain specific language yang berbasiskan Python. Dengan menggunakan trik sulap di atas, saya bisa membuat bahasa yang saya buat tadi menjadi lebih mudah dipakai. Maaf kalo saya blom bisa menjelaskan dg lebih detail.

Di Python, metaclass bisa digambarkan sebagai sebuah kode yang dijalankan saat sebuah kelas dideklarasikan. Dengan demikian kita bisa mengutak atik wujud sebuah kelas sebelum kelas teresebut siap dipakai. Contoh penggunaan dasarnya adalah sebagai berikut.

class MetaProvinsi(type):
    def __new__(cls, name, bases, attrs):
        return type.__new__(cls, name, bases, attrs)

class Provinsi(object):
    __metaclass__ = MetaProvinsi

Pada contoh di atas, ada sebuah kelas bernama Provinsi yang memiliki metaclass MetaProvinsi. Kode pada fungsi __new__ di atas adalah bagian kode yang dapat diisi untuk mengubah wujud kelas Provinsi. Fungsi ini menerima 4 buah parameter yaitu:

  1. cls yang menunjuk ke diri sendiri (yaitu MetaProvinsi),
  2. name yang berisi nama kelas yang dibuat (dalam contoh di atas, name berisi Provinsi),
  3. bases yang berisi daftar kelas yang diturunkan oleh si Provinsi (yaitu object), dan
  4. attrs yang berupa sebuah dictionary berisi daftar atribut (instance variables dan/atau methods) dari Provinsi.

Metaclass pada contoh di atas masih tidak melakukan hal apa-apa sehingga kelas Provinsi tsb sebenarnya tidak mengalami perubahan apa-apa. Sekarang mari kita ubah sedikit contoh di atas.

class MetaKabupaten(type):
    def __new__(cls, name, bases, attrs):
        attrs['nama_kelas'] = name
        return type.__new__(cls, name, bases, attrs)

class Kabupaten(object):
    __metaclass__ = MetaKabupaten

Kali ini kita mengubah dict attrs dengan menambahkan sebuah isian dengan kunci nama_kelas yang berisi nilai dari variabel name, yaitu nama kelas yang baru saja dibuat yaitu Kabupaten.

Apa bedanya contoh pertama dengan kedua? mari kita buat objek dari kelas Provinsi dan Kabupaten yang sudah dideklarasikan di atas.

p = Provinsi()
print p.nama_kelas

Andai kode di atas dijalankan, maka Python akan mengatakan bahwa atribut nama_kelas tidak ditemukan pada objek dari kelas Provinsi

AttributeError: 'Provinsi' object has no attribute 'nama_kelas'

Alasannya sudah jelas karena pada saat mendeklarasikan kelas Provinsi (maupun saat menginisialisasi kelas tersebut), kita tidak pernah membuat sebuah instance variable bernama nama_kelas. Sekarang kita coba dengan kelas Kabupaten

k = Kabupaten()
print k.nama_kelas

Bukan sulap bukan sihir, Python dapat dijalankan sampai selesai dan kita mendapat sebuah keluaran di layar seperti berikut.

Kabupaten

Keluaran tersebut dihasilkan dari k.nama_kelas yaitu nilai sebuah instance variable bernama nama_kelas dari objek k yang dibangun dari kelas Kabupaten. Kapan instance variable nama_kelas tersebut hadir? Jawabannya adalah pada saat kelas Kabupaten tersebut dibuat, lebih tepatnya dilakukan oleh metaclass MetaKabupaten.

Sekian dulu pengantar penggunaan Metaclass dari saya. Lain kali saya contohkan ilmu hitam yg sedang saya pakai maupun contoh pe(nyalah)gunaan lainnya. Contoh kode bisa dilihat di https://gist.github.com/814525

2 thoughts on “Metaclass di Python”

Leave a Reply