Metaprogramming Python
Metaprogramming adalah konsep di mana kode program dapat memanipulasi kode lainnya (seperti fungsi atau class) pada saat runtime. Singkatnya: kode yang menulis kode.
Di Python, ini adalah topik yang sangat dalam dan kompleks, tetapi sangat powerful jika digunakan dengan bijak. Salah satu fitur utama metaprogramming di Python adalah Metaclass.
1. Apa itu Class?
Sebelum memahami metaclass, ingat bahwa di Python, Class juga adalah sebuah Objek. Saat Anda mendefinisikan class, Python mengeksekusinya dan membuat sebuah objek class di memori.
class ObjectCreator:
pass
my_obj = ObjectCreator()
print(my_obj) # Instance dari ObjectCreator
print(ObjectCreator) # ObjectCreator sendiri adalah objek!
Karena Class adalah objek, maka:
- Anda bisa menyimpannya dalam variabel.
- Mengirimnya sebagai argumen.
- Menambah atribut ke dalamnya secara dinamis.
2. Fungsi type() yang Ajaib
Biasanya kita menggunakan type() untuk mengecek tipe data.
print(type(1)) # <class 'int'>
Tapi, type() juga bisa digunakan untuk membuat class secara dinamis.
Syntax: type(name, bases, attrs)
name: Nama class (string).bases: Tuple parent class (untuk inheritance).attrs: Dictionary atribut dan metode class.
# Cara Biasa
class Monyet:
def makan(self):
print("Makan pisang")
# Cara Metaprogramming (Sama persis!)
def fungsi_makan(self):
print("Makan pisang")
MonyetDinamis = type('MonyetDinamis', (), {'makan': fungsi_makan})
m = MonyetDinamis()
m.makan() # Output: Makan pisang
3. Metaclass
Metaclass adalah "pabrik" yang membuat Class.
- Objek adalah instance dari Class.
- Class adalah instance dari Metaclass.
Secara default, metaclass untuk semua kelas di Python adalah type.
class MyClass:
pass
print(type(MyClass)) # <class 'type'>
Membuat Custom Metaclass
Anda bisa membuat metaclass sendiri untuk mengontrol bagaimana sebuah class dibuat. Ini sering digunakan untuk memvalidasi atribut class atau membuat API yang ketat (seperti di Django Models).
Untuk membuat metaclass, warisi dari type. Kita gunakan argumen metaclass= di definisi class.
Contoh: Memaksa semua nama atribut class menjadi Uppercase
class UpperAttrMeta(type):
# __new__ dipanggil sebelum __init__
def __new__(upperattr_metaclass, future_class_name,
future_class_parents, future_class_attr):
# Buat dictionary atribut baru dengan kunci uppercase
uppercase_attr = {}
for name, val in future_class_attr.items():
if not name.startswith('__'): # Jangan ubah magic methods
uppercase_attr[name.upper()] = val
else:
uppercase_attr[name] = val
# Panggil type.__new__ untuk membuat class
return type(future_class_name, future_class_parents, uppercase_attr)
# Menggunakan Metaclass
class Foo(metaclass=UpperAttrMeta):
bar = 'bip'
print(hasattr(Foo, 'bar')) # False (karena diubah jadi BAR)
print(hasattr(Foo, 'BAR')) # True
print(Foo.BAR) # 'bip'
4. Kapan Menggunakan Metaclass?
Jawabannya: Hampir tidak pernah, kecuali Anda membuat framework.
"Metaclasses are deeper magic than 99% of users should ever worry about. If you wonder whether you need them, you don't." - Tim Peters (Python Guru)
Namun, memahaminya memberikan wawasan mendalam tentang bagaimana Python bekerja di balik layar.
Kesimpulan
- type() bisa membuat class secara dinamis.
- Metaclass adalah class dari sebuah Class.
- Digunakan untuk memodifikasi pembuatan Class secara otomatis.