Materi Tutorial

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:

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)

# 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.

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

Edit tutorial ini