Evet IronPython'ı kullanarak .NET sınıfları oluşturabileceğime ve bunları kullanabileceğime ikna olmuş durumdayım (sizin de ikna olduğunuzu umuyorum). Şimdi bunun ne anlama geldiğine bir bakalım. "System.Forms" isimuzayından kısa bir örnek yapmaya ne dersiniz? Bu Windows grafik kullanıcı arabirimleri oluşturmanıza imkan veren isimuzayıdır. Lafı dolandırmıyorum ve işte örneğimiz:
import clr clr.AddReference("System.Windows.Forms") from System.Windows.Forms import * class MyForm(Form): def __init__(this): Form.__init__(this) this.Text = "Class Names" this.Click += this.ClickHandler def ClickHandler(this, f, a): t = this.GetType() MessageBox.Show(t.FullName) f = MyForm() Application.Run(f)
Python'ın en sevdiğim programlama dillerinden biri olduğundan bahsetmiştim değil mi? Sebebini şimdi hatırladım. Bu kod bir pencere oluşturur ve pencerenin "Click" olayını, sınıfımızın adını gösteren bir mesaj kutusu oluşturacak şekilde yönetir.
Çeşitli .NET sınıflarını nasıl kullandığıma dikkat edin. Bu tıpkı normal Python kodu gibi ama bir farkla: Bu durumda kullandığım sınıfların hepsi "System.Windows.Forms.dll" kütüphanesinde yaşıyor. Bu kütüphanedeki sınıfları kullanmaya başlamadan önce IronPython'a bu kütüphaneyi tanıtmam gerekiyor. Bu kütüphane .NET'in standart sistemindeki kütüphanelerden biri olduğundan bu yana, tek yapmam gereken, ".dll" uzantısı olmadan kütühanenin ismini programıma dahil etmek.
clr.AddReference("System.Windows.Forms")
"AddReference" fonksiyonunu kullanabilmek için .NET kütüphanelerini programa dahil etme esnasındaki zor ve karmaşık işleri yapan "clr" modülünü programıma dahil ettim.
Şimdi IronPython bu kütüphane ile ilgili bilgiye sahip ve artık içinden istediğim herhangi bir şeyi programıma dahil edebilirim. Şu anda örneği basit tutmak istediğimden kütüphanedeki herşeyi dahil ediyorum:
from System.Windows.Forms import *
Bu satır bana ihtiyacım olan "Forms", "Application", ve "MessageBox" sınıflarını kullanma olanağını verir.
Ardından pencere için kendi sınıfımı tanımlıyorum. Sınfımı "Form" sınıfından türettim ve bir yapılandırıcı fonksiyon ile pencere tıklama olayını karşılayacak fonksiyonu yazdım. Yapılandırıcı, pencerenin "Text" özelliğine karakter tipinde bir atama yapıyor, hemen ardından kendi tanımladığım "ClickHandler" fonksiyonunun, penecerenin "Click" olayında ateşleneceğini belirtiyor. Bundan daha basit olamazdı! Sözdizimine dikkat:
this.Click += this.ClickHandler
Benim "ClickHandler" fonsiyonum da sınıfın tipini alıyor ve tipin tam ismini bir mesaj kutusunda görüntülüyor. Bu kadar basit!
Gömülü Veritipleri ve Python
Bazı gömülü Python veri tipleri hem Pythonda oldukları gibi hemde .NET sisteminde oldukları gibi gerçekleştirilmişlerdir. "String" veri tipi böyle bir örnektir. Eğer "import System" komutunu çalıştırırsanız, Pythondaki "string" değişkenleriniz .NET "string" sınıfının elemanlarını da uygulayabilir. "String" sınıfını kullanmak için "System" isimuzayını programa dahil ederek başlayın. Ardından IronPython konsolunda bir "string" tipinde değişken oluşturmayı deneyin:
>>> import System >>> a = 'hello there everybody'
"dir(a)" komutunu çalıştırarak değişkenin kullanılabilir fonksiyonlarını listeleyebilirsiniz:
>>> dir(a) ['Capitalize', 'Center', 'Clone', 'Compare', 'CompareOrdinal', 'CompareTo', 'Concat', 'Contains', 'Copy', 'CopyTo', 'Count', 'Decode', 'Empty', 'Encode', 'EndsWith', 'Equals', 'EqualsRetBool', 'ExpandTabs', 'Finalize', 'Find', 'Format', 'GetEnumerator', 'GetHashCode', 'GetLength', 'GetSlice', 'GetType', 'GetTypeCode', 'Index', 'IndexOf', 'IndexOfAny', 'Insert', 'Intern', 'IsAlnum', 'IsAlpha', 'IsDecimal', 'IsDigit', 'IsInterned', 'IsLower', 'IsNormalized', 'IsNullOrEmpty', 'IsNumeric', 'IsSpace', 'IsTitle', 'IsUpper', 'Join', 'LJust', 'LStrip', 'LastIndexOf', 'LastIndexOfAny', 'Length', 'Lower', 'Make', 'MemberwiseClone', 'Modulus', 'Multiply', 'Normalize', 'NotEquals', 'PadLeft', 'PadRight', 'RFind', 'RIndex', 'RJust', 'RSplit', 'RStrip', 'Remove', 'Replace', 'Split', 'SplitLines', 'StartsWith', 'Strip', 'Substring', 'SwapCase', 'Title', 'ToBoolean', 'ToByte', 'ToChar', 'ToCharArray', 'ToDateTime', 'ToDecimal', 'ToDouble', 'ToInt16', 'ToInt32', 'ToInt64', 'ToLower', 'ToLowerInvariant', 'ToSByte', 'ToSingle', 'ToString', 'ToType', 'ToUInt16', 'ToUInt32', 'ToUInt64', 'ToUpper', 'ToUpperInvariant', 'Translate', 'Trim', 'TrimEnd', 'TrimStart', 'Upper', 'ZFill', '__class__', '__cmp__', '__contains__', '__eq__', '__getitem__', '__getslice__', '__init__', '__len__', '__mod__', '__module__', '__mul__', '__ne__', '__new__', '__repr__', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit', 'islower', 'isnumeric', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'replace', 'rfind', 'rindex', 'rjust', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill'] >>>
Bu liste hem Python fonksiyonlarını (küçük harfle ya da altçizgi karakteri ile başlayanlar) hem de .NET "string" sınıfı fonksiyonlarını (büyük harflerle başlayanlar) içermektedir. İşte bir .NET fonksiyon çağrısı:
>>> a.Capitalize() 'Hello there everybody'
Ve burada da bir Python fonksiyon çağrısı:
>>> a.title() 'Hello There Everybody'
GetType() fonksiyonunu çağırırsanız, değişkenin .NET tipini öğrenebilirsiniz:
>>> a.GetType() System.String
Aşağıdaki kodun gösterdiği gibi, sayı tipi değişkenleri de .NET tipleri olarak kullanabilirsiniz:
>>> n = 100 >>> n.GetType() System.Int32 >>> x = 3.1415 >>> x.GetType() System.Double
Python'a özgü veri tipleride .NET sistemine yapılan çağrılarda parametre olarak kullanılabilirler. Mesela "Form" sınıfının "Controls" özelliği, "AddRange" isimli bir fonksiyon içerir. Python'a özgü bir liste tipindeki veriyi "AddRange" fonksiyonu için parametre olarak kullandığım aşağıdaki kodu bir inceleyin:
import clr clr.AddReference("System.Windows.Forms") from System.Windows.Forms import * class MyForm(Form): def __init__(self): Form.__init__(self) Button1 = Button() Button1.Top = 10 Button1.Left = 10 Button1.Text = "One" Button2 = Button() Button2.Top = 50 Button2.Left = 10 Button2.Text = "Two" ctrls = [Button1, Button2] self.Controls.AddRange(ctrls) f = MyForm() Application.Run(f)
Bu kod problemsiz bir şekilde çalışır. Eğer "AddRange" fonksiyonunun çevrimiçi yardım belgelerine bakacak olursanız, onun "Control" tipindeki nesnelerden oluşan "array" tipinde bir parametre beklediğini görürsünüz. Python'un liste veri tipi (bu koddaki "ctrls" değişkeni gibi), IronPython için benzersiz olan "IronPython.Runtime.List" adıyla gerçekleştirilmiştir. Bu kontrollerden oluşan bir "array" tipindeki değişkenden biraz farklı bir durumdur.
Peki "AddRange" fonksiyonuna Python'un liste veri tipinde bir parametreyi nasıl geçirebiliyoruz? Basit: IronPython, bir fonksiyonun hangi tipte veri beklediğini kontrol eden ve gelen veriyi ilgili tipe dönüştüren çok güçlü bir mekanizmaya sahip. Bu mekanizma sizi bir sürü gereksiz işlemden kurtarmaktadır. (Ve IronPython geliştiricilerinin bu özelliği eklemek için çok uğraştıklarını tahmin ediyorum. Dolayısı ile onlara teşekkür etmeliyiz.)
Yine de bir .NET "array" tipi değişken oluşturmak isterseniz, IronPython bunu yapmanıza izin veren bir sözdizimine de sahip. Önceki koddaki "ctrls" satırını değiştirebileceğiniz sözdizimine örnek aşağıda:
ctrls = System.Array[System.Windows.Forms.Control]( (Button1, Button2) )
Bu da "Control" nesnelerini içeren bir "array" değişken oluşturur ve isterseniz bu değişkenide "AddRange" fonksiyonuna parametre olarak geçmeyi tercih edebilirsiniz. Sözdizimine dikkat; değişkenin "System.Array" tipinde olacağını belirtiyorum, ardından tutacağı elemanların veritipini köşeli parantezler içinde belirtiyorum ve son olarak da "Button1" ve "Button2" nesneleri ile değişkenin ilk yapılandırılmasını yaparak tamamlıyorum.
Konunu tam olarak anlaşılabilmesi için, bir "array" tipi değişkenin sonuçta Python'daki liste tipinden nasıl farklı olduğundan biraz bahsetmeliyim. CLR "array" tipini doğal olarak destekler. Bu destek .NET sisteminin "Array" ismindeki sınıfı ile çok yakından ilgilidir. Doğal .NET dillerinde (özellikle C# ve VB.NET), direkt olarak "Array" sınıfının örneklerini oluşturmazsınız. Bunun yerine, bu diller, sizin CLR "array" tipinde veriler tanımlamanızı sağlayacak olan kendi özel yapılarını kullanırlar. Mesela VB.NET dilinde "Control" nesnelerinden oluşan bir "array" değişkeni şu şekilde tanımlayabilirsiniz:
Dim c(2) As Control
Bu 2 hücreli bir "array" değişken tanımlar. Eğer "c.GetType().FullName" komutunu çalıştırırsanız, "System.Windows.Forms.Control[]" ismini görürsünüz. Bu .NET sınıfı olan "Array"den türetilmiş bir CLR "array" tipi değişkenidir. Ve bu Python liste tipinden tamamen değişik bir şeydir.
Maalesef kullandığım sistemin beta versiyon olmasından dolayı, henüz "array" dönüştürme işlemi tam olarak problemsiz sayılmaz.
Yine de Python!
Eğer gerçekten Python ile ilgileniyorsanız, "getattr" fonksiyonu ile dinamik olarak nesne elemanlarına ulaşabilme gibi özelliklerden haberdarsınızdır. Bu fonksiyon IronPython içindede mevcut ve .NET sınıfları üzerinde de işini yapıyor. Şuna bir bakın:
>>> import System >>> import clr >>> clr.AddReference("System.Windows.Forms") >>> from System.Windows.Forms import * >>> >>> btn = Button() >>> btn.Height = 30 >>> hasattr(btn, 'Height') True >>> getattr(btn, 'Height') 30 >>> setattr(btn, 'Height', 50) >>> btn.Height 50
Tabii ki hala aktif olan "delattr" fonksiyonu .NET sınıflarından türetilmiş sınıflarda işe yaramıyor. Şunu belirtmeliyim ki, önceden mevcut bir sınıfın mevcut bir özelliğini silmek sistemin yapısına ciddi zararlar vermeden, pek mümkün değildir.
Reprinted from DevSource.com, a Ziff Davis Media property, all rights reserved, Ziff Davis Media, 28 East 28th St., New York, NY, USA