27 Ağustos 2008 Çarşamba

Turşular ve Birkaç Os Fonksiyonu - 1

Python kodlaması yaparken, terminalde çok sık kullandığım birçok komutu birer parametreyle halledebileceğim bir program yazmıştım ve geçenlerde de duyurmuştum: Tiss. Parametresiz haliyle, sadece uzantılarına göre silmesini istediğim dosyaları, boş dizinleri ve python programı inşa ederken ortaya çıkan inşa dizinini siliyor. Örneğin, hede.txt dosyasını Vim'de yazıp tekrar kaydettiğimde, aynı dizinde hede.txt~ dosyası oluşuyor. Bir tane olsa hadi neyse; ama bazen .pyc, #, ~, .db gibi bir sürü gereksiz dosya öyle birikiyor ki, gerçekten tek bir komuta ihtiyacınız olabiliyor. Hangi parametreyle, ne yaptığını sitesindeki[1] kodlara bakarak görebilirsiniz. Yakında ana sayfasına parametreler hakkında bilgi gireceğim.

Sonra dedim ki, ben parametresiz haliyle belli uzantılara sahip dosyaların silmesini sağlıyor olabilirim; ama ya kullanıcı bu uzantıları değiştirmek isterse? Ya benim öntanımlı olarak yazdığım uzantıların birkaçını kaldırmak istiyorsa? Bu halde kullanıcıyı, koda elle müdahale etmeye ve sonra tekrar kurmaya zorlamış olmuyor muyum? Oluyorum tabi ki..

Bu nedenle, birçok program gibi, Tiss'in de ev dizininde, ayar dosyalarının saklandığı bir dizin olacaktı: .tiss. Kodu açıp baktığımda, uzantıları bir listede tuttuğumu gördüm:


backup_extensions = ['*~', '#*#', '*.db', '*.lay', '*.pyc', '*.log', '*.ini']


Hmm. Şimdi şöyle yapabiliriz. Eğer kullanıcı programı ilk defa çalıştırıyorsa veya ayarlarda hiçbir değişiklik yapmamışsa, öntanımlı olarak yukarıdaki listeyi silme fonksiyonunda kullanacağız. Hadi yapalım. Önce bize lazım olacak modülleri içe aktaralım:


import os, glob, pickle


Şimdi de lazım olacak değişkenleri tanımlayalım:


class files:
def __init__(self):
self.home = os.environ['HOME']
self.tiss_home = os.path.join(self.home, '.tiss')
self.data_remove = os.path.join(self.tiss_home, 'remove.pickle')


os.environ['HOME'] ile, kullanıcının ev dizininin çıktısını alıyoruz. os.path.join'i kullanarak ev dizin yoluna '.tiss' ekliyoruz. Üçüncü değişkeninse ikinci değişkenden bir farkı yok. Şimdi bu değişkenleri kullanarak .tiss dizininin varlığını kontrol edelim:


def create_dir_files(self):
if not os.path.exists(self.tiss_home):
os.mkdir(self.tiss_home)
self.backups()


Yani kod diyor ki, eğer kullanıcının ev dizininde .tiss diye bir dizin yoksa, önce onu oluştur, sonra da self.backups() fonksiyonunu çalıştır. Eee, o fonksiyon nerede ve neye yarar? Hemen söylüyorum. O fonksiyon, Tiss'in ana görevi olan gereksiz uzantıları silme görevi için kullanıcının belirlediği herhangi bir ayar dosyası yoksa, öntanımlı backup_extensions listesini remove.pickle isimli bir dosyada turşu gibi saklamaya yarar. İşte kodumuz:


def backups(self):
if not os.path.exists(self.data_remove):
backup_extensions = ['*~', '#*#', '*.db', '*.lay', '*.pyc', '*.log', '*.ini']
pickle_file = file(self.data_remove, 'w')
pickle.dump(backup_extensions, pickle_file)
del pickle_file


İyi de, niye böyle bir şey yaptık? Doğrudan backup_extensions değişkenini, gereksiz uzantıları silmeye yarayan fonksiyonda kullanmayı neden denemedik? Deneyebilirdik; ama kullanıcıya bu değişkeni değiştirmekten mahrum da bırakırdık. O nedenle turşu olarak bir dosyaya yazdırma gereği duyduk. Ha, illa ki turşu mu? Elbette değil, dileseydik, doğrudan bir dosya açıp oraya satır satır yazdırmayı deneyebilirdik; ama satırı çağırmak, “\n”lerle uğraşmak, split'lemek, sonra kullanıcının isteği doğrultusunda satırı değiştirmek, sonra yazdırıp dosyayı tekrar kapatmak.. İnanın, bana turşu denen bir şey varken bu amaç için başka yolu seçmek, css ile siteyi bölümlere ayırmak varken tablolarla bölmek, yani tabloları amacı dışında kullanarak siteyi ve kodu ağırlaştırmak gibi geliyor. Şimdi, turşuda saklanan değişken lazım olduğunda, nasıl çağrılır ve kullanılır onu gösterelim. Önce kod, sonra açıklaması:


def remove_files():
pickle_file = file(self.data_remove)
backup_extensions = pickle.load(pickle_file)
for remove in backup_extensions:
backup_files = glob.glob('%s/' % os.getcwd() + remove)
for backup in backup_files:
os.remove(backup)


Kodda da görüldüğü gibi, bir öncekinden farklı olarak, yazma izni vermeden pickle_file değişkenine self.data_remove yolunu atıyoruz. Sonra turşumuzda duran listeyi backup_extensions ile çağırıyoruz. Çağırdıkdan sonra da, bu listedeki her eleman için, bulunduğumuz dizinde tarama yapıyoruz. Eğer bulunduğumuz dizinde, backup_extensions'taki uzantılardan herhangi birine sahip dosyalar bulunursa, onun için de ikinci bir döngü başlıyor: O uzantılara sahip dosyaları sil!

Evet. Buraya kadar öntanımlı listemizi nasıl turşu olarak saklayabileceğimizi, sonra lazım olduğunda nasıl çağırabileceğimizi görmüş olduk. Ama bizim amacımız neydi? Kullanıcıya bu listeyi değiştirme hakkı vermekti. Bunun için izlenecek adımlar da basit:


  • Silme için bir ayar fonksiyonu oluştur.

  • Bu fonksiyon için bir parametre ata.

  • Fonksiyonda bir değişkene düzenlenebilir olarak turşuyu çağır.

  • Kullanıcıya hangi uzantıların silinmesini istediği üzerine soru sor.

  • Eklenen ve çıkarılan uzantı elemanlarını tekrar turşuya kaydet.

  • Ve kapat.



Bu fonksiyonu da daha sonraki tarihte anlatırım. Eğer bu yazı ile ilgili bir yanlışlık veya daha iyi yöntem bulursanız, buraya mutlaka yorum olarak girmenizi istiyorum. Biz neydik? Python öğrenmeye ve onu tüm esnekliğiyle kullanmaya hevesli öğrencilerdik. Şimdiden teşekkürler.




[1] http://tiss.googlecode.com

25 Ağustos 2008 Pazartesi

Set

Set fonksiyonu bir veri tipi içerisinde yer alan değerleri bulup ayrıştırmaya yarar. Bir kaç örnekle daha iyi anlaşılacaktır:
In ile başlayan satırlar verdiğimiz komutu, out ile başlayanlar ise o komutun çıktısını belirtiyor.

In [7]: a=set("Antalya")
In [8]: a
Out[8]: set(['A', 'a', 'l', 'n', 't', 'y'])

Büyük ve küçük harfe duyarlı olduğuna dikkat ediniz.


In [17]: list=["antalya","adana","antalya","izmir","ankara","izmir"] #liste,tüp ve sözlükler üzerinde de kullanabilirsiniz.
In [18]: list2=set(list)
In [19]: list2
Out[19]: set(['ankara', 'antalya', 'adana', 'izmir'])
In [21]: sozluk={"fenerbahce":"sarikanaryalar","galatasaray":"aslanlar","besiktas":"karakartal","fenerbahce":"fb","galatasaray":"gs"}
In [22]: s2=set(sozluk)
In [23]: s2
Out[23]: set(['fenerbahce', 'besiktas', 'galatasaray'])


Şimdi bir kaç faydalı özellik daha gösterelim.

In [30]: a=set("adanaAntalya")
In [31]: b=set("afyonAnkara")

In [32]: a-b #a'nın b'den farklı elemanları.
Out[32]: set(['t', 'd', 'l'])

In [33]: a|b # Tüm elemanlar
Out[33]: set(['a', 'A', 'd', 'f', 'k', 'l', 'o', 'n', 'r', 't', 'y'])

In [34]: a&b # Ortak elemanlar
Out[34]: set(['a', 'A', 'y', 'n'])

In [35]: a^b #a ya da b'de olup fakat ortak olmayan elemanlar.
Out[35]: set(['d', 'f', 'k', 'l', 'o', 'r', 't'])

List Comprehension

Türkçesi için uygun bir karşılık bulamadığım için python dökümantasyonun da olduğu gibi yazdım. (Uygun bir karşılığı varsa ya da uydurursanız yorum belirtirseniz değiştirmek taraftarıyım.)

Daha önce Mirat Can Bayrak'ın anlatmış olduğu map() ve filter() fonksiyonlarının yaptığı işleri ve çok daha fazlasını yapabilmemize olanak sağlar. Anlaşılması biraz zor gelebilir fakat alıştıktan sonra hayat kurtarıcı olabiliyor. Sözü fazla uzatmadan hemen örnekler üzerinde açıklamaya başlayalım.

İlk örneğimiz map() fonksiyonunun anlatıldığı örneğin aynısı olsun


In [65]: def sayhello(to_who):
print "hello %s" %to_who
....:
....:

In [67]: people = ('Ahmet','Mehmet','Hale','Jale','Bülent')
In [68]: [sayhello(i) for i in people] #lc (List Comprehension)'ın olayı burada başlıyor. Kolay anlayabilmek için sağdan-sola doğru okuyunuz. "i İnsanların içerisinde olduğu sürece sayhello() fonksiyonunu çalıştır"
hello Ahmet
hello Mehmet
hello Hale
hello Jale
hello Bülent


Örneklere yine Mirat Can Bayrak'ın filter()
fonksiyonunu anlattırken kullandığı tek sayilar üzerinden gidelim.

In [72]: [i for i in range(10) if i%2!=0] #Gördüğünüz gibi lc içerisinde if koşullarınıda kullanabiliyoruz.
Out[72]: [1, 3, 5, 7, 9]


Biraz abartıp iç içe döngüleri kullarak sadece TEK satırda amatör bir çarpım tablosu bile yapabiliriz.

In [77]: [[i*j for i in range(1,10)] for j in range(1,11)]
Out[77]:
[[1, 2, 3, 4, 5, 6, 7, 8, 9],
[2, 4, 6, 8, 10, 12, 14, 16, 18],
[3, 6, 9, 12, 15, 18, 21, 24, 27],
[4, 8, 12, 16, 20, 24, 28, 32, 36],
[5, 10, 15, 20, 25, 30, 35, 40, 45],
[6, 12, 18, 24, 30, 36, 42, 48, 54],
[7, 14, 21, 28, 35, 42, 49, 56, 63],
[8, 16, 24, 32, 40, 48, 56, 64, 72],
[9, 18, 27, 36, 45, 54, 63, 72, 81],
[10, 20, 30, 40, 50, 60, 70, 80, 90]]

Lc ile yapabilecekleriniz sizin yaratıcılığınıza kalmış

>>> [i for i in range(3,100,2) if (i%3!=0 and i%5!=0 and i%7!=0)]
[11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97] #asal sayılar.

In [90]: us_al=dict([(i,i**2) for i in range(2,10)]) #dict() ile lc'den aldığımız veriyi bir sözlüğüde aktarabiliyoruz.
In [91]: us_al
Out[91]: {2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

23 Ağustos 2008 Cumartesi

Liste metodları

append

Yazım
ListObject.append(nesne)
Açıklama
Liste sonuna bir nesne ekler, nesne string yada integer olabilir.
Örnek:
>>> meyveler.append('karpuz')
>>> print meyveler
['elma','armut','limon','karpuz']

count

Yazım
ListObject.count(nesne)
Açıklama
Verilen nesnenin listede kaç adet olduğunu döndürür , nesne string yada integer olabilir.
Örnek
>>> print meyveler.count('karpuz')
1

extend

Yazım
ListObject.extend(taşıyıcı)
Açıklama
Listeyi verilen taşıyıcıdaki elemanlarla genişletir, taşıyıcı tüp yada liste olabilir.
Örnek>>> eklenecekler = ('portakal','mandalina','muz')
>>> meyveler.extend(eklenecekler)
>>> print meyveler
['elma', 'armut', 'erik', 'limon', 'karpuz', 'portakal', 'mandalina', 'muz']

index

Yazım
ListObject.index(nesne)
Açıklama
Nesnenin liste içerisinde kaçıncı eleman olduğunu döndürür. eğer verilen eleman listede yoksa hata mesajı döndürür. nesne string yada integer olabilir.
Örnek
>>> print meyveler.index('erik')
>>> 2

insert

Yazım
ListObject.insert(sıra,nesne)
Açıklama
Listenin belirlenen sırasına nesneyi ekler. Verilen sıradan sonraki elemanlar ileri ittirilir. Nesne integer yada string olabilir.
Örnek>>> print meyveler
['elma', 'armut', 'erik', 'limon', 'karpuz', 'portakal', 'mandalina', 'muz']
>>> meyveler.insert(2,'kiraz')
>>> print meyveler
['elma', 'armut' ,'kiraz', 'erik', 'limon', 'karpuz', 'portakal', 'mandalina', 'muz']

pop

Yazım
ListObject.pop()
Açıklama
Listenin sonundan bir eleman döndürür ve o elemanı siler. Bu özellik append() ile birlikte kullanıldığında listelerin stack gibi kullanılabilmesini sağlar.
Örnek>>> sonelelman = meyveler.pop()
>>> print soneleman
muz
>>> print meyveler
['elma', 'armut' ,'kiraz', 'erik', 'limon', 'karpuz', 'portakal', 'mandalina']

gördüğünüz gibi soneleman değişkeni meyvelerin son elemanı olan muz oldu ve meyveler listesi bir eksildi.

remove

Yazım
ListObject.remove(eleman)
Açıklama
Listede verilen elemanı arar bulduğu ilk eşleşmeyi siler. Eğer verilen eleman listede yoksa hata döndürür.
>>>meyveler.append('elma')
>>> print meyveler
['elma', 'armut' ,'kiraz', 'erik', 'limon', 'karpuz', 'portakal', 'mandalina', 'elma']
>>> # şu anda listede 2 adet elma var
>>> meyveler.remove('elma')
>>> print meyveler
['armut' ,'kiraz', 'erik', 'limon', 'karpuz', 'portakal', 'mandalina', 'elma']
>>> meyveler.remove('elma')
>>> print meyveler
['armut' ,'kiraz', 'erik', 'limon', 'karpuz', 'portakal', 'mandalina']

reverse()

Yazım
ListObject.reverse()
Açıklama
Listedeki elemanların sırasını tersine çevirir.['armut' ,'kiraz', 'erik', 'limon', 'karpuz', 'portakal', 'mandalina']
Örnek>>> print meyveler
['armut' ,'kiraz', 'erik', 'limon', 'karpuz', 'portakal', 'mandalina']
>>> meyveler.reverse()
>>> print meyveler
['mandalina', 'portakal', 'karpuz', 'limon', 'erik', 'kiraz', 'armut']

Liste veri tipi

Listeler,sözlükler ve tüpler containers dediğimiz taşıyı veri tipi grubuna aittirler.

Listeler ardaşık veri listeleridirler. Liste elemanları köşeli parantez içine alınır ve , (virgül işareti) ile ayrılırlar. elemanlar herhangi bir veri tipinde olabilir.
meyveler = ['elma' , 'armut' , 'ayva']
sayilar = [1,3,5,10]
karisik = ['bir string',4,2]

Liste elemanlarına meyveler[kaçıncı eleman] şeklinde ulaşılabilir. Yukarıdaki meyveler listesindeki armut elemanını yazdırmak için.
print meyveler[1]
armut

Şeklinde çağırılabilir. Çeşitli şekillerde içeriği değiştirilebilir. Örneğin listedeki 2. elemanı limon olarak değiştirmek için.
meyveler[2] = 'limon'
print meyveler
['elma','armut','limon']

Not: Python saymaya 0 dan saymaya başlar. Bu sebepten yukarıda armut 2. değil 1. eleman olarak çağırıldı.

Alfanümerik veri tipleri (Strings)

Bir karakter katarı saklamak için kullanılır. Python da string'ler bir yada birden fazla satır karakter katarı saklayabilirler. En basit hali ile bir değişkene karakter katarı atamak :
Değişken = 'değişkene atanacak metin'
şeklinde olur. Bu atama sırasında " (çift tırnak) yada ' (tek tırnak) işaretlerinden biri kullanılır. Buradaki amaç metin içerisinde bu karakterlerden biri varsa diğerini kullanmaktır.

metin = " bu metin içinde ' karakteri barındırabiliyor."
metin = ' bu metin de içinde " karakteri bulundurabiliyor.'

peki bu iki karakterin ikiside bize gerekseydi ne yapacaktık? burada \ (backslash) karakteri bahsi geçen bize sorun çıkartacak tırnak işaretinin önüne getirilir.
metin = "bu metin içerisinde hem ' karakterini hem \" karakterini kullanabiliyorum"
Eğer girilecek metin çok uzunsa \ (backslash) karakteri metni bölüp alt alta yazmak için kullanılabilir.
Değişken = 'Bu metin çok uzun olduğu için \
backslash karakteri ile bölünüp alt alta yazılmış\
böylelikle kod içerisinde çirkin, upuzun bir satır\
oluşmasına engel olunmuştur'


Bu uzun satır sorununa alternatif bir çözüm ise string'i """ (üç tırnak) işareti altına almaktır.

Değişken = '''Bu metin tıpkı backslash ekleme yönteminde
olduğu gibi alt alta yazılmış fakat üç tırnak
işaretleri arasına alınıp satır sonlarında \ işareti kullanılmamış.'''

22 Ağustos 2008 Cuma

Instant python helper for Geany

In English


  • Watch that video first.. did you like it?
  • Download that file and save it to your /usr/bin/ folder
  • Do not forget giving running permissions (chmod +x pydocw vs.)
  • Look for filetypes.python in ~/.geany/filedefs if there is not download from here.
  • In your filetypes.python file find that line
    context_action_cmd =
    and change it to
    context_action_cmd = pydocw %s
  • From options menu in geany find keybindings tab and change context-action key to your own keyboard shortcut (i'm using ctrl+l)
  • Restart Geany, open a python file , select a function and press your shortcut to get help about it. It must be worked.

Türkçe



Önce şuradaki video yu izleyin.Beğendiyseniz suyu aktı ise şu işlemleri yapın.
  • Şuradaki pydocw dosyasını indirip /usr/bin/ klasörünüze kopyalayın.
  • Bunu yapmadan önce "sudo chmod +x pydocw" diyerek çalışma izni vermeyi unutmayın garibana.
  • ~/.geany/filedefs klasörünüze eğer filetypes.python dosyası yoksa şuradan alıp koyun.
  • Bu dosya içerisindeki context_action_cmd = satırını bulun ve = in karşısına "pydocw %s" ekleyip (" işareti hariç) kaydedin.
  • Geany'yi açın seçenekler menüsünden, keybindings sekmesine girin ve context-action un karşısına "l" yada istediğiniz başka bir kısa yolu yazın.
  • Geany'yi kapatıp açın. Bir python dosyası açın, herhangi bir python objesi seçip alt+l tuşuna basarak gerekli yardımı alın.

Gtk - TextView

İlk yazıyı okuduysanız gtk.TextView objesini inceleyerek başlayabiliriz.

TextView widgetini oluşturmak için tek bir fonksiyon bulunur.
gtk.TextView(buffer=None)
Bir TextView yaratıldığında ona arkadaş TextBuffer ve TextTagTable aletleri de ön tanımlı olarak yaratılır. Eğer bu aletlerden halihazırda olanlar kullanılmak istenirse örneğin şu şekilde değiştirme işlemi yapılabilir.
textview.setbuffer(buffer)
TextView içinden TextBuffer nesnesi alınmak istenirse :
buffer = textview.get_buffer()
TextView nesnesinin salt okunur olmasını:
textview.set_editable(setting)
şeklinde sağlayabiliriz. Buradaki setting True ise kullanıcı metni düzenleyebilir ,False ise düzenleyemez. TextView'ın düzenlenebilir olup olmadığını :
is_editable = textview.get_editable()
şeklinde alabiliriz. TextView düzenlenemez halde olduğunda kullanıcıya kürsör göstermenin manası yoktur. O yüzden genelde bu modda iken:
textview.set_cursor_visible(False)
diyerek kürsörün gözükmesine engel olunur.
Gtk TextView daki metnin uzun satırlarının alt satıra geçirilmesi işlemini otomatik olarak yapabilmenizi sağlar. Bunun için sadece
textview.set_wrap_mode(wrap_mode)
kullanmanız yeterlidir. Burada bahsi geçen wrap_mode 3 değer alabilir bunlar :
  • gtk.WRAP_NONE
  • gtk.WRAP_CHAR
  • gtk.WRAP_WORD

değerleridir. İsimleri kendilerini açıkladığı için bunlar tek tek açıklama yapmıyorum.
TextView nesnelerindeki metni hizalamak, ve nasıl hizalandığı bilgisini almak için şu iki metod kullanılır.
textview.set_justification(justification)
justification = textview.get_justification()

Burada bahsi geçen justification 3 değer alabilir, bunlar :
  • gtk.JUSTIFY_LEFT
  • gtk.JUSTIFY_RIGHT
  • gtk.JUSTIFY_CENTER

Not : Eğer metnin otomatik satır bölme modu WRAP_NONE ise hizalama sadece JUSTIFY_LEFT olur.
TextView içindeki taglar öntanımlı hizalama ayarlarının üstüne yazarlar.

TextView ile ilgili diğer özellikler aşağıdaki gibi alınabilir ve ayarlanabilir.

textview.set_left_margin(left_margin)
left_margin = textview.get_left_margin()

textview.set_right_margin(right_margin)
right_margin = textview.get_right_margin()

textview.set_indent(indent)
indent = textview.get_indent()

textview.set_pixels_above_lines(pixels_above_line)
pixels_above_line = textview.get_pixels_above_lines()

textview.set_pixels_below_lines(pixels_below_line)
pixels_below_line = textview.get_pixels_below_lines()

textview.set_pixels_inside_wrap(pixels_inside_wrap)
pixels_inside_wrap = textview.get_pixels_inside_wrap()

textview.set_tabs(tabs)
tabs = textview.get_tabs()


Burada bahsi geçen left_margin, right_margin, indent, pixels_above_lines, pixels_below_lines ve pixels_inside_wrap parametreleri piksel cinsinden belirtilmişlerdir.

Örnek olarak pygtk-demo'içerisindeki TextView başlıklarına bakabilir , buradaki kodu inceleyebilirsiniz.

Kaynak : http://www.pygtk.org/pygtk2tutorial/sec-TextViews.html

Gtk - TextView nesnelerine genel bakış

TextView çok satırlı metin düzenleme işlemlerinde kullanılan bir alettir.

TextBuffer, TextView ile gösterilen metni barındıran taşıyıcıdır.

TextIters, TextBuffer içinde 2 karakter arasında kalan alanı içerir (rö? Sanırım text editörlerdeki seçim şeysi gibi). TextIter aletleri TextBuffer içindeki metin değiştirilene kadar geçerlidir. Bu alet TextBuffer aletleri ile baş edebilmek için kullanılan en önemli alettir.

TextMarks, TextBuffer değiştirildiğinde , içindeki pozisyonları korumak için kullanılır. Bir Mark TextIter gibi 2 karakter arasındaki alanı içerir. Fakat TextBuffer değiştiğinde kendini korur. TextMark'lar anonim yada isimlendirilerek kullanılabilirler. Her TextBuffer öntanımlı olarak isimleri insert ve selection_bound adında 2 adet TextMark'a sahip olarak yaratılır.

TextTags, TextBuffer içinde belli bir alan içerisindeki metin içerisinde değiştirilebilir özellikleri betimler.Her TextBuffer o buffer içinde geçerli tagları taşıyan TextTagTable'a sahiptir. Bı TextTagTable'lar genelliği sağlamak için TextBuffer'lar arasında paylaşılabilir.

Bundan sonraki yazılarda bu bahsi geçen nesneleri tek tek inceleyeceğiz.

21 Ağustos 2008 Perşembe

Filter

Ben bu gece yazı yazmaktan kusmaz isem filter kullanımını öğreneceğiz hep birlikte...
filter bir listede ayıklama yapmaya yarar. Elinizdeki listeden belli kurallara uymayan elemanları çıkarmak istediğinizde uzun uzun döngüler kurmak yerine filter fonksiyonunu kullanabilirsiniz.
Kullanımı:
filter (fonksiyon , liste)
Şeklindedir listedeki her eleman fonksiyona tek tek parametre olarak gönderilir, eğer fonksiyon true olarak dönüyorsa listedeki eleman silinmez false olarak dönüyorsa silinir. Hemen güzel bir örnek ile pekiştirelim.
Önce tek parametreye sahip, verilen parametrenin 2 ye bölümünden kalan 0 dan büyükse (yani verilen sayı tek sayı ise) True döndüren bir fonksiyon belirleyelim.
def is_odd(number):
return number % 2 > 0

Şimdi elimizdeki bir sayı listesine bu fonksiyonu
def is_odd(number):
return number % 2 > 0
numbers = range(10) # 10'a kadar olan sayıları içeren bir liste
odds = filter(is_odd,numbers)
print odds
[1,3,5,7,9]

Biraz daha neşelendirip bu fonksiyonu lambda ile tanımlarsak.. Program tek satıra iniyor.

odds = filter(lambda number : number % 2 > 0, range(10))
print odds
[1,3,5,7,9]

Map

Map işimizi hayli kolaylaştıran işlemlerden biri. Bir fonksiyonu bir dizi değişkenle birlikte tekrar tekrar çağırmanız gerektiğinde map fonksiyonunu kullanıyoruz.
Yazımı:
map(fonksiyon,parametre listesi)
şeklindedir. Parametre listesindeki her öğe için fonksyion tekrar çağırılır ve parametre olarak geçirilir.
def say_hello(to_who)
print "hello", to_who
people = ('Ahmet','Mehmet','Hale','Jale','Bülent')
map(say_hello,people)

Yukarıdaki örnek say_hello fonksiyonunu people içindeki her öğe için tekrar tekrar çağırarak.
hello Ahmet
hello Mehmet
hello Hale
hello Jale
hello Bülent

Çıktısını üretecektir. Ayrıca şurada Gökmen'in lamda ve map'ı birarada kullanarak yaptığı örneği incelemeyi unutmayın

Sayısal veri tipleri (Integers)

Not: Sağ tarafta gördüğünüz anket sonuçlarında başlangıç seviyesinde olanlar için daha çok şey yayınlanmalı sonucu çıkmış. Anketlere kayıtsız kalmadığımızı bilmenizi isterim.

Sayısal ifadeleri tutmak için kullanılır. en basit hali ile bir değişkene sayısal veri atamak:
Değişken = Sayı
Şeklinde olur. Python verdiğiniz sayının cinsini otomatik olarak algılayıp değişken tipinizi otomatik olarak belirler. Eğer sayısal veri tipi el ile ayarlanmak isteniyorsa ilgili sayısal sınıf ile birlikte çağırılır.

Python'da Kullanılabilen Sayısal Veri Tipleri.
Atama şekli Anlamı
sayi = int(13)sayi = integer tipinde 13 sayısı
sayi = float(13)sayi = float tipinde 13 sayısı
sayi = long(13)sayi = long integer tipinde 13 sayısı
sayi = octal(13)sayi = octal (8'lik sayı sisteminde) integer tipinde 13 sayısı
sayi = hex(13)sayi = hexadecimal (16'lık sayı sisteminde) tipinde 13 sayısı

Lambda

Lambda fonksiyonları , karmaşık olmayan fonksiyonları hemen tek satırda ifade etmemizi sağlar. Nasılmı?

def is_odd(number):
return number % 2 > 0 # sayının 2 ye bölümünden kalan 0 dan büyüktür önermesini döndür.


yerine

is_odd = lambda number : number % 2 > 0 # döndürülecek değer de : işaretinden sonra yazılıyor.
^ parametreler
burada
sıralanıyor.


Şeklinde yazabiliriz. Lambda fonksiyonları tanımlarken virgül koyarak birden fazla parametre belirleyebiliriz

Örneğin aşağıdaki fonksiyon 2 kenar açısını parametre olarak alıp üçgenin 3. açısını döndürüyor.

find_angle = lambda a, b : 180 - (a + b)
print find_angle(30,60)
90


Abartıp lambda fonksiyonları tanımlarken argüman tipi parametreler oluşturabiliriz.

find_angle = lambda a = 10 ,b = 20 : 180 -(a , b)
print find_angle(a=50) # b yi belirtmediğimiz için default değeri 20 kabul edilecek
110


özetle şunu kafanıza kazıyın : lambda parametreler : döndürülecek sonuç

19 Ağustos 2008 Salı

Tisssss, Tisssss!

Python'da programlama yaparken işleri terminalden yürütmek açıkçası bana çok fazla zaman kazandırıyor; ama bazen feci yanlışlar yaptığım oluyor. Mesela, yanlışlıkla *.pyc'leri de svn'ye aktarmak (özellikle bkz: Mirat Can Bayrak), build dizinini silmek yerine src dizinini svn'ye atamadan yanlışlıkla silmek vesaire..

Bu tip felaketlerin üstesinden gelmek için, ben de ilk başlarda "silgi" diye bir program yapmıştım. Amacım boş dizinleri ve inşa dosyalarının bulunduğu "build" dizinlerini silmek, *.pyc, *~, *#, *.db ve benzeri işime yaramayacak dosyaları tek seferde yok etmekti.

Programı yaparken başta, genel bir amaç edinmeyi düşünmüştüm. Sonra ne olduysa, bu programı salt python programcılara yönelik olarak tekrar tasarlayıp, ismini de "tiss" diye değiştirdim. Önce küçük bir şemayla, programın planını göstereyim:


src dizininde iki önemli .py dosyası var. "remove.py" dosyasında, tiss'in ana fonksiyonu olan silme fonksiyonunu tanımladım, "main.py"de de belli parametreler dahilinde çeşitli işlemler tanımlanıyor. Her parametre için gerektiğinde ayrı modul dosyası oluşturup sonradan import edebiliriz.

Peki bunları size niye anlatıyorum? Eğer sizin de bir fikriniz varsa, modülünüzü yazıp bana gönderesiniz diye =) Kodları ve fikri gerçekten beğenirsem, buradan size svn hesabı verme sözü de veriyorum, herhangi bir eşeklik olursa iptal edebilirim de :P. Hadi, Tiss'i kendi isteğimize göre şekillendirelim. İşte tiss burada:

http://tiss.googlecode.com

(Bu arada diyagram çok uyduruk olmuş ama Mirat'ın yazısı gaza getirdi, bir başlangıç yapalım dedik, heheh.)

18 Ağustos 2008 Pazartesi

Uml Modelleme - 1

Uml (unified modelling language) karmaşık bir sistemin elemanlarını , değişkenlerini çalışma prensipleri gibi bilgileri grafiksel şemalar ile ifade etmemize yarar. Uml sayesinde bir satır kod yazmadan bütün programın nasıl çalışacağını şema üzerinde görebilir, açıklarını-ihtiyaçlarını tespit edebiliriz. Tahmin edebilirsiniz ki bütün sistemi daha en başından basit bir şekilde modellemek sistemin açıklarını baştan görmek inanılmaz büyük bir avantaj.

Başka bir konu da anlaşılabilirlik... projenize dışardan biri katıldığı zaman birkaç saat içerisinde sizin projenizin bütün çalışma prensibini anlayabilir geriye ayrıntılar kalır.

Buradaki bahsi geçen sistem çok geniş bir kavramdır, vücudun çalışması, karayolu trafiği , yazdığımız program... herşey bu uml ile modellenebilir. Bu noktada uml: sınıf diagramı ,bileşen diagramı, birleşik yapı diyagramı gibi çeşitlere ayrılır. Biz bu yazımızda sınıf diagramları ile ilgileneceğiz.

Sınıf diagramı wikipedia da şu cümleyle açıklanmış : "Sınıf Diyagramı ("Class Diagram") vasıtası ile Nesnel Yönelimli Programlamada temel teşkil eden sınıflar net şekilde gösterilebilir ve böylece sağlanan ek görsellik ile yazılım tasarlamanın ilerleyen aşamalarında daha yüksek verimlilik sağlanabilir."

Buraya kadar herşey tamam. Peki bir uml şeması neye benzer diyecek olursanız ?? Aşağıdaki örneği verebiliriz


Şimdilik bu kadarı tanışma için yeterli sanırım. Bir daha ki yazıda burada gördüğümüz şekillerin anlamlarından bahsedeceğim.

15 Ağustos 2008 Cuma

Kurtar Beni Lambda

Bazen öyle şeylere ihtiyaç duyuyorum ki, "Bunun için de şimdi bilmem kaç satır döngü oluşturmaya değer mi?" diye düşünmeden olmuyor. Mesela XfceP'i yaparken de öyle bir olayla karşılaşmıştım.

Sizi bilmem ama, böylesi basit bir şey için döngü oluşturmayı da fazlasıyla lüks buldum, o nedenle de lambda bazı yerlerde gerçekten işe yarayan bir araç. Özellikle, for döngüsü içinde birkaç tane daha döngü kurunca, bir tiksinti kaplıyor içimi, şu linkte[1] anlatıldığı gibi:

nums = range(2, 50)
for x in nums:
divided = False
for i in range(2, x - 1):
if (x % i) == 0:
divided = True
if divided == False:
print x,

Halbuki lambda bu karışıklıktan tek bir satırda kurtulmanıza izin veriyor:

>>> nums = range(2, 50)
>>> for i in range(2, 8):
... nums = filter(lambda x: x == i or x % i, nums)
...
>>> print nums
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

Lambda'nın, map & filter & reduce hedelerine ise daha sonra değinirim artık..

[1]: http://www.secnetix.de/olli/Python/lambda_functions.hawk

14 Ağustos 2008 Perşembe

Pyton ve Nesnel Programlama

Nesnel programlama sizin programınızı gerçek dünyadaki sistemler gibi modelleyebilmenizi sağlayan bir güzelliktir , kim icat ettiyse elleri öpülesi mukaddes bir insandır.

  • Nesnel yaklaşımda bir sınıf yaratılır, sınıf bir genellemedir. Belli bir grup nesnenin ortak özelliklerini barındırır(örn: organism sınıfı bütün organizmalarda bulunan işlem ve özellikleri barındırır.)

  • Nesne bu sınıf'ın bir nesneye uygulanmasıdır animal = organism() yada human = organism() dediğimiz zaman buradaki animal ve human birer nesnedir.

  • Sınıf özellikleri bu sınıfa ait özelliklerdir. Örneğin her organizmanın bir yaşı vardır. Bu yaş bigisini organism sınıfı üzerinde age olarak tanımlarsak [1] daha sonra bu sınıfa ait nesnelerin age özelliğini animal.age şeklinde çağırabiliriz.

  • Bir sınıf kendi özelliklerini kendi kendine de değiştirebilir. Bu durumda self.ozellik = hede şeklinde kullanılır. Buradaki aslında self sınıfın kendisini ifade eder. Eğer bir fonksiyon içerisinde self. kullanılacaksa o fonksiyonun argümanı içerisinde self bulumalıdır.[2]

  • Bir nesne oluşturuluyorken __init__ fonksiyonu otomatik olarak çağırılır.

  • Bir nesne siliniyorken __del__ fonksiyonu otomatik olarak çağırılır. Eğer del(nesne) kullanılarak nesne silinmez ise nesne program sonunda silinir.


  • __init__ ve __del__ fonksiyonları self argümanı ile belirtilmek zorundadır.

  • örnek olarak bir organizma sınıfı şu şekilde tanımlanabilir.
    class organism:
    def __init__(self):
    print "ben doğdum"
    self.age = 0 [1]
    def grow_up(self,years):
    self.age += years
    def __del__(self):
    print "ben öldüm"
    animal = organism()
    print "animal age is :",animal.age
    animal.grow_up(3) # grow up 3 years
    print "animal age is :", animal.age

Kodlarken

Python ile programlama yaparken proje arkadaşım Mirat'le beraber (hatta ona çaktırmadan) bir kural listesi oluşturmuştum. Paylaşayım dedim:
  • Programın anadili İngilizce olmalı.
  • Noktalama işaretlerinden önce boşluk bırakılmaz, sonra bırakılır.
  • Operatörlerden hem önce, hem de sonra boşluk bırakılır.
  • (), {} ve []'lerden önce boşluk bırakılmaz, sonra bırakılır; hatta bir alt satıra konulur.
  • Eğer çıktı ekrana yazdırılacaksa " "; yazdırılmayacaksa ' ' kullan.
  • Her fonksiyonun altına açıklama gir.
  • Türkçe'mizi güzel kullanalım, trafik kurallarına uyalım.
  • Her fonksiyon, sınıf, döngü ve try - except arasında bir satır boşluk olsun.
  • Tab mutlaka 4 boşluk olarak ayarlanmalı.
  • Emacs veya Vim'in güzelliği, gereksiz boşlukları göze batırıp (hele ki emacs'te) kodu kirli göstermesindedir. Gereksiz boşluklar, Emacs'te kırmızı arkaplan, Vim'de ise nokta şeklinde gözükür.
  • Fonksiyon ve sınıf isimleri İngilizce olmalı. Eğer birden fazla kelimeden oluşuyorsa, boşluk yerine alt çizgi konulmalı ve hepsi küçük harfle yazılmalı; veya boşluk bırakmaksızın, sonraki kelimenin ilk harfi büyük yazılmalı. Örneğin:

    def check_local_folder():
    print "hede"

    def CheckLocalFolder():
    print "dede"

Evet çok acemice; ama biz bunları uyguluyoruz. Bir de boşluklara çok mu kafayı taktık, ne.. Bu arada Alper Kanat'ın önerileriyle bir iki şey değiştirdim. Esasında biz bunu uyguluyoruz :P

PyGtk ile HelloWorld

İnternette Gtk ile ilgili Türkçe bir döküman aradığınızda bilgiden çok küfür var nedense. Aman abi sen ne yapıyorsun ,acayip zor ,imkansız sadece über-geek'ler gtk kullanarak programlama yapabilir. Gtk ile programlama yapanın geyşası olurum gibi yorumlar yükseliyor. Bende bu sebepten başlangıçta kendimi qt yolunda zorlamıştım fakat yapamadım. Gtk fetişim xfce ile birlikte nirvanasına ulaştı genç zihnime bir karabasan gibi bulaştı. fazla lafı uzatmadan gtk nedir ne değildir diye kimseyi yormadan Türk internet medyasını büyük bir açlıktan kurtarayım dedim.
PyGtk hello world şeysi.
İlk önce glade denen tasarım aracımızla en basit manada bir arayüz tasarlayalım. Yorumları tahmin edebiliyorum neden arayüzü glade ile yapıyorsun delikanlı gibi kodlayarak yapsana diye.. css olmadan html kodlamak neyse glade olmadan gtk kodlamak (diğer gui api'lerini bilmediğim için birşey söyleyemiyorum) odur. Glade ile arayüzünüzü tarif eden bir xml dosyası oluşturursunuz. Sonra bunu programınızın içinde ayrıştırır ("parse" demeyeceğim) kullanırsınız. Kodunuz ayrı tasarımınız ayrı olur , 1000 satırlık değil 100 satırlık kodla güreş tutarsınız gözleriniz şeş beş bakmazsınız.

  • Yeni bir glade dosyası açın

  • bir adet window ekleyin

  • içine bir adet button nesnesi ekleyin, etiketine hello world gibi bişi yazın

  • pencerenin ismi w1, düğmenin ismi d1 olsun.


Sinyaller ve işleyiciler:
Sinyal'ler aslında hareketlerdir düğmeye basıldı, nesne yokedilmek istendi , sürükleyip bıraktılar beni vs gibi. İşleyici de bu aksiyon karşısında widget'in arkadaşlarına ne diye bağırdığı desek yeridir. Örneğin b1 tuşu tıklandığı zaman "bana tıkladılar imdat" diye bağırıyor , ve bunu dinlemekle görevli olan fonksiyon bu sesi duyunca yettim gayri değip çalışmaya başlıyor...

  • w1 widget'ının (Türkçesini bulursam yazıcam) sinyaller sekmesine girin GtkObject altındaki destroy sinyalinin yanına "w1_kapatilmak_istendi" yazın.

  • b1 widget'ının sinyaller sekmesine gidin clicked sinyalinin yanına işleyici olarak "d1_basıldı" yazın.

  • dosyayı hello.glade adıyla kaydedin.


Godlamaya başlayabiliyin aybalam:
En sevdiğiniz editörle yeni bir python dosyasına başlayın en sevdiğiniz 2 satırı bu dosyanın başına yazın.
#!/usr/bin/env python
# -*- coding: utf-8 -*-

ilk önce pygtk modülünü ve sys modülünü import eyleyin.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pygtk ,sys

sonra pygtk ya senin bana version 2.0'ın lazm değilsen işime yaramazsın diyeceğiz. pygtk.require('2.0') eğer exception kaldırırsa versionu 2.0 dan aşağı demektir o zaman program çalışmasın.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pygtk, sys

try:
pygtk.require('2.0')
except:
print "versiyon tutmadı..."
sys.exit(1)


Eğer pygtk 2.0 var ise geri kalan gerekli modülleri import edelim..
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pygtk, sys
try:
pygtk.require('2.0')
except:
print "versiyon tutmadı..."
sys.exit(1)

import gtk , gtk.glade

Şimdi glade dosyamızı ayrıştıralım , içinden w1 ve b1 nesnemizi kullanmak üzere birer değişkene atayalım.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pygtk, sys

try:
pygtk.require('2.0')
except:
print "versiyon tutmadı..."
sys.exit(1)

import gtk , gtk.glade

window_tree = gtk.glade.XML('hello.glade')
window = self.wtree.get_widget('w1')
button = self.wtree.get_widget('b1')

Artık bu nesnelere ait işlemleri gerçekleştirebiliriz. ama önce programa hangi sinyali ne için kullanacağımızı belirtelim bunu yapmak için hangi işleyicinin hangi fonksiyonu tetikleyeceğini bir sözlük üzerinde topluyor sonra autoconnect ile bu işlemleri fonksiyonlara bağlıyoruz.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pygtk, sys
try:
pygtk.require('2.0')
except:
print "versiyon tutmadı..."
sys.exit(1) # [*1]

import gtk , gtk.glade

window_tree = gtk.glade.XML('hello.glade')
window = self.wtree.get_widget('w1')
button = self.wtree.get_widget('b1')
signals = {'w1_kapatilmak_istendi' : end_program,
'd1_basıldı' : end_program}
window_tree.signal_autoconnect(signals)


Gördüğünüz gibi tuşa basıldığı zaman ve pencere kapatılmak istendiği zaman end_program fonksiyonuna yönlendiriyoruz... peki bu end_program fonksiyonunu nasıl tanımlayacağız?
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pygtk, sys
try:
pygtk.require('2.0')
except:
print "versiyon tutmadı..."
sys.exit(1) # [*1]

import gtk , gtk.glade

window_tree = gtk.glade.XML('hello.glade')
window = self.wtree.get_widget('w1')
button = self.wtree.get_widget('b1')
signals = {'w1_kapatilmak_istendi' : end_program,
'd1_basıldı' : end_program}

def end_program(self,widget,data=None):
print "Güle güle..."
gtk.main_quit()

# sinyalleri bağlamadan önce fonksiyonların
# tanıtılmış olması gerekiyor

window_tree.signal_autoconnect(signals)

Burada dikkat etmemiz gereken şey şu gtk nın sinyalleri tarafından çağırılan fonksiyonların zorunlu olarak alması gereken sırasıyla self, widget , data=None argümanları.. Aslında bunu ezberleyin çünkü hep bu şekilde kullanacaksınız.
Widget'larla işimiz bittiğine göre w1'e göster kendini emrini verelim. ve son olarak gtk ya ben işimi bitirdim bundan sonra kontrol sende demek için gtk.main() diyelim.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pygtk, sys
try:
pygtk.require('2.0')
except:
print "versiyon tutmadı..."
sys.exit(1) # [*1]

import gtk , gtk.glade

window_tree = gtk.glade.XML('hello.glade')
window = self.wtree.get_widget('w1')
button = self.wtree.get_widget('b1')
signals = {'w1_kapatilmak_istendi' : end_program,
'd1_basıldı' : end_program}

def end_program(self,widget,data=None):
print "Güle güle..."
gtk.main_quit()

window_tree.signal_autoconnect(signals)
gtk.main()
window.show()


işte sonuç...


Buradaki kodların boşluk karakterlerinde falan bozukluk olabilir siz en iyisi kodlara şuradan da bir bakın.


hello.py
hello.glade