Özel Metaclass Oluşturma
Python’da sınıf oluşturma sürecini, sınıf tanımında metaclass anahtar sözcüğünü geçirerek özelleştirebiliriz. Bu, bu anahtar sözcüğü zaten geçirmiş bir sınıftan miras alınarak da yapılabilir.
class MyMeta(type):
pass
class MyClass(metaclass=MyMeta):
pass
class MySubclass(MyClass):
pass
Aşağıda MyMeta sınıfının türünün type olduğunu ve MyClass ile MySubClass’ın türünün MyMeta olduğunu görebiliriz.
print(type(MyMeta))
print(type(MyClass))
print(type(MySubclass))
<class 'type'>
<class '__main__.MyMeta'>
<class '__main__.MyMeta'>
Bir sınıf tanımlanırken herhangi bir metaclass belirtilmemişse, varsayılan type metaclass’ı kullanılır. Bir metaclass verilmişse ve type()’ın bir örneği değilse, doğrudan metaclass olarak kullanılır.
__new__ ve __init__
Metaclass’lar aşağıda gösterilen iki yoldan biriyle de tanımlanabilir. Aralarındaki farkı aşağıda açıklayacağız.
class MetaOne(type):
def __new__(cls, name, bases, dict):
pass
class MetaTwo(type):
def __init__(self, name, bases, dict):
pass
__new__, sınıf oluşturulmadan önce dict veya bases demetlerini tanımlamak istediğinizde kullanılır. __new__’ün dönüş değeri genellikle cls’in bir örneğidir. __new__, değiştirilemeyen türlerin alt sınıflarının örnek oluşturmayı özelleştirmesine olanak tanır. Sınıf oluşturmayı özelleştirmek için özel metaclass’larda geçersiz kılınabilir. __init__ ise genellikle nesne oluşturulduktan sonra onu başlatmak için çağrılır.
Metaclass __call__ yöntemi
Resmi belgelere göre, sınıf çağrıldığında özel davranışa izin veren özel bir __call__() yöntemi metaclass’ta tanımlanarak diğer sınıf yöntemleri de geçersiz kılınabilir.
Metaclass __prepare__ yöntemi
Python’un veri modeli belgelerine göre
Uygun metaclass belirlendikten sonra sınıf ad alanı hazırlanır. Metaclass’ın bir __prepare__ özniteliği varsa, sınıf tanımından gelen ek anahtar sözcük argümanlarıyla birlikte namespace = metaclass.__prepare__(name, bases, **kwds) olarak çağrılır. Metaclass’ın bir __prepare__ özniteliği yoksa, sınıf ad alanı boş, sıralı bir eşlem olarak başlatılır. - docs.python.org
Bir Metaclass kullanarak Singleton Tasarımı
Bu, bir sınıfın örneklenmesini yalnızca bir nesneyle sınırlandıran bir tasarım desenidir. Örneğin veritabanına bağlanmak için bir sınıf tasarlarken faydalı olabilir. Bağlantı sınıfının yalnızca tek bir örneğine sahip olmak isteyebilirsiniz.
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
Sonuç
Bu yazıda, metaclass’ların ne olduğunu ve Python programlamamızda onları nasıl uygulayabileceğimizi öğrendik. Metaclass’lar; günlükleme, sınıfların oluşturulma anında kaydedilmesi ve profilleme gibi alanlarda uygulanabilir. Oldukça soyut kavramlar gibi görünüyorlar ve bunlara gerçekten ihtiyacınız olup olmadığını merak ediyor olabilirsiniz. Uzun yıllardır Python kullanan Tim Peters bu soruyu en iyi şekilde yanıtlıyor.
"Metaclass’lar, kullanıcıların %99’unun asla dert etmemesi gereken daha derin büyülerdir. Onlara ihtiyacınız olup olmadığını merak ediyorsanız, yoktur (onlara gerçekten ihtiyaç duyanlar buna kesin olarak emindir ve nedenine dair bir açıklamaya ihtiyaç duymazlar).” - realpython
Python hakkında daha fazla bilgi edinmek isterseniz, DataCamp’in Python Programlama beceri yoluna başlayın ve Python Sınıfları Eğitimimize göz atın.

Python’da bir metaclass, bir sınıfın nasıl davranacağını tanımlayan sınıfın sınıfıdır. Bir sınıfın kendisi bir metaclass örneğidir. Python’da bir sınıf, o sınıfın örneğinin nasıl davranacağını tanımlar. Metaclass’ları iyi anlamak için önceden Python sınıflarıyla çalışma deneyimine sahip olmak gerekir. Metaclass’lara derinlemesine dalmadan önce birkaç kavramı aradan çıkaralım.
Python’da her şey bir nesnedir
Python sınıfları dinamik olarak oluşturulabilir
Python’daki
type, bir nesnenin türünü bulmamızı sağlar. Yukarıda oluşturduğumuz nesnenin türünü kontrol edebiliriz.Bir dakika, ne oldu? Yukarıda oluşturduğumuz nesnenin türünün class olmasını beklerdik, ama değil. Bu düşünceyi aklınızda tutun. Birazdan bunu ele alacağız. Ayrıca
type’ın kendi türünün detypeolduğunu görüyoruz. O,type’ın bir örneğidir.type’ın yaptığı bir başka sihir de sınıfları dinamik olarak oluşturmamızı sağlamasıdır. Bunu aşağıda nasıl yapacağımızı gösterelim. Aşağıda gösterilenDataCampsınıfı,typekullanılarak şu şekilde oluşturulabilir:Yukarıdaki örnekte
DataCampsınıf adıyken,DataCampClasssınıfın referansını tutan değişkendir.typekullanırken, aşağıda gösterildiği gibi bir sözlük aracılığıyla sınıfın özniteliklerini iletebiliriz:PythonClass’ımızınDataCampsınıfından miras almasını istersek,typeile sınıfı tanımlarken ikinci argümana bunu geçiririzArtık bu iki kavramı aradan çıkardığımıza göre, Python’un sınıfları bir metaclass kullanarak oluşturduğunu fark ediyoruz. Python’da her şeyin bir nesne olduğunu gördük, bu nesneler metaclass’lar tarafından oluşturulur. Bir sınıf oluşturmak için
classdediğimizde, perde arkasında sınıfı oluşturan sihri yapan bir metaclass vardır. Bunu pratikte yukarıdatypeile zaten gördük. Bu, string’leri oluşturanstrve tamsayıları oluşturanintgibidir. Python’da___class__özniteliği, mevcut örneğin türünü kontrol etmemizi sağlar. Aşağıda bir string oluşturalım ve türünü kontrol edelim.type(article)kullanarak da türü kontrol edebiliriz.str’ın türünü kontrol ettiğimizde, onun da type olduğunu görürüz.float,int,list,tuplevedictiçin türü kontrol ettiğimizde benzer bir çıktı alırız. Bunun nedeni, bu nesnelerin tümününtypetüründe olmasıdır.type’ın sınıfları oluşturduğunu zaten gördük. Dolayısıyla__class__’ın__class__’ını kontrol ettiğimizde, bununtypedöndürmesi gerekir.