Lewati ke konten utama

Pengantar Metaclass di Python

Dalam tutorial ini, pelajari apa itu metaclass, cara mengimplementasikannya di Python, dan cara membuat yang kustom.
· 6 mnt Baca

Jelajahi bersama AI

Metaclass di Python adalah kelas dari sebuah kelas yang menentukan bagaimana sebuah kelas berperilaku. Sebuah kelas sendiri merupakan instance dari metaclass. Kelas di Python menentukan bagaimana instance dari kelas tersebut akan berperilaku. Agar benar-benar memahami metaclass, Anda perlu memiliki pengalaman sebelumnya bekerja dengan kelas-kelas Python. Sebelum kita menyelami metaclass lebih jauh, mari kita bereskan terlebih dahulu beberapa konsep.

Semua Hal di Python adalah Objek

class TestClass():
    pass

my_test_class = TestClass()
print(my_test_class)
<__main__.TestClass object at 0x7f6fcc6bf908>

Kelas Python dapat Dibuat secara Dinamis

type di Python memungkinkan kita mengetahui tipe sebuah objek. Kita bisa lanjut memeriksa tipe objek yang kita buat di atas.

type(TestClass)
type
type(type)
type

Tunggu, apa yang baru saja terjadi? Kita berharap tipe objek yang kita buat di atas adalah class, tetapi ternyata bukan. Simpan dulu pertanyaan itu. Kita akan membahasnya sebentar lagi. Kita juga melihat bahwa tipe dari type sendiri adalah type. Ia merupakan instance dari type. Hal ajaib lain yang dilakukan type adalah memungkinkan kita membuat kelas secara dinamis. Mari tunjukkan bagaimana cara melakukannya di bawah ini. Kelas DataCamp di bawah ini akan dibuat seperti ditunjukkan menggunakan type:

class DataCamp():
    pass
DataCampClass = type('DataCamp', (), {})
print(DataCampClass)
print(DataCamp())
<class '__main__.DataCamp'>
<__main__.DataCamp object at 0x7f6fcc66e358>

Pada contoh di atas DataCamp adalah nama kelas sementara DataCampClass adalah variabel yang menampung referensi kelas. Saat menggunakan type kita dapat meneruskan atribut kelas menggunakan dictionary seperti ditunjukkan di bawah ini:

PythonClass = type('PythonClass', (), {'start_date': 'August 2018', 'instructor': 'John Doe'} )
print(PythonClass.start_date, PythonClass.instructor)
print(PythonClass)
August 2018 John Doe
<class '__main__.PythonClass'>

Jika kita ingin PythonClass mewarisi dari kelas DataCamp kita teruskan ke argumen kedua saat mendefinisikan kelas menggunakan type

PythonClass = type('PythonClass', (DataCamp,), {'start_date': 'August 2018', 'instructor': 'John Doe'} )
print(PythonClass)
<class '__main__.PythonClass'>

Setelah dua konsep itu kita singkirkan, kita menyadari bahwa Python membuat kelas menggunakan metaclass. Kita telah melihat bahwa semua hal di Python adalah objek, dan objek-objek ini dibuat oleh metaclass. Setiap kali kita memanggil class untuk membuat kelas, ada metaclass yang melakukan sihir pembuatan kelas di belakang layar. Kita sudah melihat type melakukannya secara praktik di atas. Ini mirip dengan str yang membuat string dan int yang membuat bilangan bulat. Di Python, atribut ___class__ memungkinkan kita memeriksa tipe dari instance saat ini. Mari buat sebuah string di bawah ini dan periksa tipenya.

article = 'metaclasses'
article.__class__
str

Kita juga dapat memeriksa tipenya menggunakan type(article).

type(article)
str

Saat kita memeriksa tipe dari str, kita juga mengetahui bahwa tipenya adalah type.

type(str)
type

Saat kita memeriksa tipe untuk float, int, list, tuple, dan dict, kita akan mendapatkan keluaran serupa. Ini karena semua objek tersebut bertipe type.

print(type(list),type(float), type(dict), type(tuple))
<class 'type'> <class 'type'> <class 'type'> <class 'type'>

Kita sudah melihat type membuat kelas. Oleh karena itu saat kita memeriksa __class__ dari __class__ seharusnya mengembalikan type.

article.__class__.__class__
type

Membuat Metaclass Kustom

Di Python, kita dapat menyesuaikan proses pembuatan kelas dengan meneruskan kata kunci metaclass dalam definisi kelas. Ini juga bisa dilakukan dengan mewarisi kelas yang sudah meneruskan kata kunci ini.

class MyMeta(type):
    pass

class MyClass(metaclass=MyMeta):
    pass

class MySubclass(MyClass):
    pass

Kita dapat melihat di bawah bahwa tipe kelas MyMeta adalah type dan bahwa tipe dari MyClass dan MySubClass adalah MyMeta.

print(type(MyMeta))
print(type(MyClass))
print(type(MySubclass))
<class 'type'>
<class '__main__.MyMeta'>
<class '__main__.MyMeta'>

Saat mendefinisikan kelas dan tidak ada metaclass yang didefinisikan, metaclass bawaan type akan digunakan. Jika metaclass diberikan dan bukan instance dari type(), maka metaclass tersebut digunakan langsung sebagai metaclass.

__new__ dan __init__

Metaclass juga dapat didefinisikan dengan salah satu dari dua cara yang ditunjukkan di bawah ini. Kita akan jelaskan perbedaannya di bawah.

class MetaOne(type):
    def __new__(cls, name, bases, dict):
        pass

class MetaTwo(type):
    def __init__(self, name, bases, dict):
        pass

__new__ digunakan saat seseorang ingin mendefinisikan dict atau tuple bases sebelum kelas dibuat. Nilai kembalian dari __new__ biasanya sebuah instance dari cls. __new__ memungkinkan subclass dari tipe immutable menyesuaikan pembuatan instance. Ini dapat dioverride dalam metaclass kustom untuk menyesuaikan pembuatan kelas. __init__ biasanya dipanggil setelah objek dibuat untuk menginisialisasinya.

Metode Metaclass __call__

Menurut dokumentasi resmi, kita juga dapat menimpa metode kelas lain dengan mendefinisikan metode __call__() kustom di metaclass yang memungkinkan perilaku kustom saat kelas dipanggil.

Metode Metaclass __prepare__

Menurut dokumentasi model data Python

Setelah metaclass yang sesuai diidentifikasi, namespace kelas dipersiapkan. Jika metaclass memiliki atribut __prepare__, ia dipanggil sebagai namespace = metaclass.__prepare__(name, bases, **kwds) (di mana argumen kata kunci tambahan, jika ada, berasal dari definisi kelas). Jika metaclass tidak memiliki atribut __prepare__, maka namespace kelas diinisialisasi sebagai pemetaan terurut kosong. - docs.python.org

Desain Singleton menggunakan Metaclass

Ini adalah pola desain yang membatasi instansiasi sebuah kelas hanya menjadi satu objek. Ini bisa berguna misalnya saat merancang kelas untuk menyambung ke basis data. Seseorang mungkin ingin hanya memiliki satu instance dari kelas koneksi.

class SingletonMeta(type):
    _instances = {}
    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(SingletonMeta,cls).__call__(*args, **kwargs)
        return cls._instances[cls]

class SingletonClass(metaclass=SingletonMeta):
    pass

Kesimpulan

Pada artikel ini, kita telah mempelajari apa itu metaclass dan bagaimana kita dapat mengimplementasikannya dalam pemrograman Python kita. Metaclass dapat diterapkan dalam logging, pendaftaran kelas saat waktu pembuatan, dan profiling, antara lain. Konsep ini tampak cukup abstrak, dan Anda mungkin bertanya-tanya apakah Anda perlu menggunakannya sama sekali. Pythonista jangka panjang, Tim Peters, menjawab pertanyaan itu dengan sangat baik.

"Metaclasses are deeper magic than 99% of users should ever worry about. If you wonder whether you need them, you don’t (the people who actually need them know with certainty that they need them, and don’t need an explanation about why).” - realpython

Jika Anda ingin mempelajari lebih lanjut tentang Python, mulailah jalur keterampilan Python Programming dari DataCamp dan lihat Tutorial Kelas Python kami.

Referensi

Tautan satu

Tautan dua

Topik

Terkait

blogs

Tutorial Korelasi di R

blogs

40 Pertanyaan Wawancara DBMS Teratas di 2026

blogs

Spaghetti Plot dan Jalur Badai