“Hiç uğraşamam…”
Ve metaclass’lar. Örnek kodlara, açıklayıcı belgelere ve Guido van Rossum tarafından yazılıp Fred L. Drake, Jr. tarafından düzenlenmiş bir HOWTO Metaclasses kitabına rastlanmasa da aslında gayet basit bir konu. İlk bakışta mantığını anlamak güç gelebilir ancak üstüne gittiğinizde gerçekten kolay ve kullanışlı olduğunu fark edeceksiniz.
Nedir Metaclass’lar? Metaclass’lar basitçe açıklamak gerekirse “bir sınıfın sınıfıdır”. Bir sınıf, metaclass olacak şekilde tanımlanmış bir sınıfı metaclass olarak alıyorsa, o sınıfın örneğidir. Metaclass’lar genel olarak kapsayıcı (wrapper) olarak kullanılırlar. Bu size biraz Descriptor mantığını hatırlatabilir ancak farkını örnek kodlarda göreceksiniz.
Metaclass’ları tanımlarken, taban sınıf ( baseclass, superclass ) “type” olmalı. Bunun dışında tabii diğer tanımlanmış Metaclass’lar da olabilir. Her sınıf gibi Metaclass’larda da ilk önce __new__() ve sonrasında __init__() metodları çağrılır. Metaclass’larda fark olarak bu çağrılardan sonra __call__() metodu çağrılmaktadır. Bu çağrıların parametreleri şu şekilde:
__new__(metacls,name,bases,dict)
metacls: Metaclass olarak tanımlanmış sınıf. Hatırlarsanız __new__() metoduna giden ilk parametre örneği oluşturulacak sınıfın kendisiydi.
name: Metaclass’ı kullanan sınıfın ismi. String bir değer.
bases: Metaclass’ı kullanan sınıfın kullandığı/türetildiği taban sınıflar.
dict: Metaclass’ı kullanan sınıfın niteliklerini barındıran sözlük.
__init__(self,name,bases,dict)
self: Biliyorsunuz, Metaclass’ı kullanan sınıf aynı zamanda Metaclass’ın bir örneği olduğu için ilk parametre o.
name, bases ve dict parametreleri __new__ metoduna gönderilen parametrelerle aynı.
__call__(self[,arg1,arg2,arg3...])
Sanırım burda parametreleri açıklamaya pek de gerek yok
Örnek bir Metaclass tanımlayıp kullanalım.
Şimdi adım adım bakacak olursak:
İlk olarak söylediğim gibi __new__ metodu çağrılıyor. Giden parametreler sırasıyla:
<class ‘__main__.Meta’> Sinif (<type ‘object’>,) {‘__module__’: ‘__main__’, ‘__metaclass__’: <class ‘__main__.Meta’>}
Ve __new__ metodu bize verilen parametreler ile bir örnek, bir nesne oluşturup döndürüyor.
İkinci adımda ise __init__ metodu çağrılıyor. Burda da giden parametreler sırasıyla şu şekilde:
<class ‘__main__.Sinif’> Sinif (<type ‘object’>,) {‘__module__’: ‘__main__’, ‘__metaclass__’: <class ‘__main__.Meta’>}
Gördüğünüz gibi __init__ metodunun gelen parametreleri ekrana bastırmak başka bir işlemi yok.
Son olarak ise __call__ metodu çağrılıyor. İşte Sinif’in Meta sınıfının örneği olduğunu bize gösterecek çağrı. Sınıf Özellikleri ve Yeni Stil Sınıflar yazımda bahsettiğim __call__ metodu kullanımını hatırlayın, sınıf örneğinin çağrılabilir fonksiyon gibi davranmasını sağlıyordu. Örnek vermek gerekirse
__call__ metodunun Metaclass kullanımında yarattığı etki de aynı. Metaclass’ı kullanan sınıf, orneklendirildiği anda tanımlıysa __new__ ve sonrasında __init__ metodları çağrılırken, bir yandan da Metaclass sınıfının örneği olduğu için Metaclass’da tanımlanmışsa __call__ metodunu çağırıyor. Farkı anlamak için Meta ve Sinif orneklerinin bulunduğu örnek kodda “Sinif(‘deneme’)” vb. değişiklikler yapabilirsiniz.
Bitti. Kaynaklara bir göz atın derim. Özellikle descintro’da yer alan autoprop ve autosuper örnekleri çok ilginizi çekecek ( o kadar kullanışlılar ki, Pisi‘nin kaynak kodlarında “Guido’s cool metaclass examples. fair use. ahahah. I find these quite handy. Use them : )” açıklama satırlarıyla kendilerine rastladım. Burada ) Ayrıca metaclass’ların önceki yapıda nasıl kullanıldığını öğrenmek de faydalı olacaktır.
http://www.python.org/download/releases/2.2.3/descrintro/#metaclasses
http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python
http://gnosis.cx/publish/programming/metaclass_1.html
http://en.wikibooks.org/wiki/Python_Programming/MetaClasses
http://www.voidspace.org.uk/python/articles/metaclasses.shtml
http://effbot.org/zone/metaclass-plugins.htm
http://pastebin.com/pBL5H6Dn ( Gene Singleton, bu sefer Metaclass olarak, “Thinking in Python” kitabından, “The pattern concept” başlığı altında )
Ve…
http://en.wikipedia.org/wiki/Metaclass
http://en.wikipedia.org/wiki/Metaobject_protocol
http://www.eksisozluk.com/show.asp?t=aspect+oriented+programming
http://en.wikipedia.org/wiki/Aspect_Oriented_Programming
Dahası da size kalmış…
Metaclass konusuna değinmiş olduğuma göre tasarım desenlerine geçmeden önce aklıma gelen bilumum gereksiz programlamaya zaman ayırarak fena bir şekilde eğlenip cozutabilirim.
Tags: metaclass, __metaclass__
Posted in Python · Temmuz 15th, 2010 · Comments (0)
No comments yet