5
Mar

Tam iki sene önce yani ben daha lise hayatıma yeni başladığım zamanlarda, Python öğrenme çabalarım sürüyordu. O günlerde öğrendiğim yeni şeyleri oturup, uygulamam akılda kalması için ve pratikleşmem için çok gerekliydi. Ben de bir oyun yapayım dedim. Arkadaşlarımla nasıl bir şey yaparız diye fikir yürütürken en son aklıma – Bir odadan kaçış oyunu yapalım, karakter bir şekilde odadan kaçmaya çalışsın, kendini yesin, şeklinde bir konsept geldi.

Nasıl yapılır demeden oturup, direk başladık. Henüz Okan ile Furkan’ın Python’dan haberi olmadığı sıralarda oturup ana harita çizimleri yapıp, üzerinde x,y de hareket ettirdim. Hikaye konusunda fikirlerini alarak bilgisayar odasında çalışarak bitirdiğimiz,(inanılmaz bir şekilde ilkeldi, o yüzden kayboldu diyebilirim.(görmek bile istemiyorum)) projemizin adı F(urkan)O(kan)D(oğan) projesi oldu. Google Code sayfası fod-project idi. Neyse bir sene sonra Furkanlar Eskişehir’e taşındıklarında OD – project olarak kaldık. Baş harfi eksikti.

Yeni proje arayışlarıda olan ben, bir ada-yaşam oyunu yapalım diye bir fikir ortaya attım. Kareli deftere haritayı çizdik. Okan artık Python hakkında az da olsa bilgiliydi. Okan’a harita tasarımcılığını üstlendi. OD olarak kalan projenin başına Mert’in (sözde) katılması ile proje “mod-project” oldu. (hala adı da öyle)

İşleri svn deposundan götürdük. Kayıtlara şuradan(ilk zamanları) bakabilirsiniz. Yeni öğrendiğim dictionary(sözlük) nesnesini kullanarak şöyle bir harita sistemi oluşturdum.

elf.map11 = {
“15,2″:[ "             ___","            /  X","         __/    ","        /       ","   ____/        ","  (             "],
“14,2″:[ "             ___","            / X ","         __/    ","        /       ","   ____/        ","  (             "],

gibi  bir yapısı vardı. Yani x,y’de kordinatı veriyordunuz o konumda X’in durduğu haritayı alıyordunuz. Bu zahmetli yazım işini Okan üstlendiği için benim için pek problem olmadı. Ama bu tüm yapı hem zaman kaybı hem de büyük bir karmaşıklığa sürükledi oyunu.  mod-tra yani mod-training aslında haritası planladığımızdan küçük olan ve bizim için denemelik alt proje idi. En son bütün bir karmaşıklık beni deli etti. Her şey birbirine girdi sinirlenip geliştirmeye ara verdim. Zaten M ve O’da pek oralı olmamıştı. :)

Bu arada ben, o mod-project deposunu çok ilginç denemelerde kullandım. Örneğin QTCPServer kullanarak internet üzerinden oynanabilen bir taş-makas-kağıt oyunu yaptım. (Sunucu tarafında yaptığım hileden sinirlenen arkadaşlarımın hala o “Nasıl ya?” diyişleri kulaklarımda)

Okan da bu arada “Rus Ruleti” çalışmalarına başladı “Ek” klasörü altında. Ben de PyQt denemelerime devam ettim. En son mod-xml diye XML’den de haritayı çağırıp üzerinde oynatabilmiştim.

Ocak ayında Okan ile eski günlerin anısında mod-xmlv2 yapalım dedik. O bir daha harita tasarımcısı oldu. Oturdu uğraştı. XML biçimini değiştirdi. Ben de mini bir oyun motoru yazdım. W-A-S-D-E-Q ile anında konsoldan oynanabilen, oyun bitişinde şu kadar saniye de kaçtın diye zevkli bir oyun denemesiydi. Oyun motoru aslında oyun yapmak isteyenler için örnek olabilir, hatta istediğiniz büyüklükte harita yapabilirsiniz. Onun dışında en son oyunu bitirdiğimizde aklımda XML’de oyunu bitirebiliriz gibi fikirler geldi. Tüm o karakter hareketlerini vs. Kısacası yeni bir dil gibi bir şey olacaktı. Ama zaman yetmedi.

Şu an oyunu proje sitesinden svn ile çekip mod-xmlv2′den oynayabilirsiniz.(mod-project’in M’si olan Mert ise 14 saniyelik rekorunda çok iddaalı.)

Oyunun hikayesinden sonra biraz teknik detaya inersek oyun, XML’i okuyan minik bir motoru var. Bu parça XML’deki tagleri parçalayıp alan ve harita olan kısmı okuyan bölüm. xml.dom.minidom ile yapıldı. Oyun aslında gitmek için sadece bir ileride verdiğiniz ilerleme komutuna bağlı olarak kordinatın yürünebilir (-,/ vs) işareti olmayan yer varsa boşluk ise yürüyor. Nesneler Y(yatak), M(masa) şeklinde isimlendirilmiş şekilde. Üzerine geldiğinizde nesne hakkındaki bilgiler, eğer yapabiliyorsanız masanın altına bakabiliyorsunuz. En son odadan çıkmaya çalışıyorsunuz.

Mantık olarak böyle biz yaparken çok eğlendik, denerseniz sizde eğlenebilirsiniz. Oyun projeleriniz varsa alıp, bu mini oyun motorunu ilham alarak(ya da direk kopyalayıp) kendi oyununuzu yapabilirsiniz. Bizim 3 senedir uğraştığımız, en doğru yöntemi nasıl buluruz diye harcadığımız 3 yılı kazanabilirsiniz. (Baya ara verdik ondan 3 sene oldu.)

Bu arada sadece tek bağımlılığı var o da Python :) Konsoldan güzel güzel oynamanızı ve odadan kolay kaçmalar diliyorum.

svn checkout http://mod-project.googlecode.com/svn/trunk/ mod-project

‘i konsola yazıp direk indirebilirsiniz.

(Bunu unutmadan yazmam gerekiyordu. :) )

28
Nis

Geçen günlerde  bir e-posta aldım. E-posta’da bir listenin kopyasının nasıl yapıldığı soruluyordu. Ve ‘a=b’ gibi bir yöntemin işe yaramadığı belirtiliyordu. Birkaç deneme ve Osman Karagöz ile konuşmamdan sonra işin mantığını bir de buradan açıklamak istedim.

#İlk önce iki liste belirleyelim
 
a = ['1','2','3','4']
b = [ ] #bu liste boş
 
#Şimdi b'yi a'ya eşitleyelim
 
b=a
 
#Çıktılarını alalım
 
print b
print a
 
#Şimdi a'daki tüm elemanları silelim
 
for i in range(4):
    a.pop(0)
 
# Bir daha çıktı alalım
 
print b
print a

Sorun bu son çıktıların ne olacağı idi. İlk cevap a’nın boş, b’nin dolu olması olarak düşünebilirsiniz. Fakat iki liste de boş olacaktır.

b=a dediğimizde a’nın verilerine bağlantı açmış oluyoruz. Yani ikisinden birinden bir veri silersek o zaman ikisinden de silinmiş olacaktır. Eğer bir veri eklersek ikisine de eklenmiş olacaktır. Peki tam bir kopyalama istersek ne yapmalıyız ?

for i in a:
    b.append(i)

dersek a’nın tam bir kopyasını b’de sahip olacağız.

İyi Pythonlamalar!

13
Nis

Evet, süpriz!

Geçen yıl PyGuguk adında bir guguklu saat yaptığımı hatırlıyorum. Tabi amatör bir uygulamaydı. Beklerken ana döngüyü bölemediği için donup kalıyordu ve kapatmak imkansızdı. Kontrolcu projesi ile uğraşırken öğrendiğim QThread ve Guguk için gereken QTimer ile artık guguklu saatimiz donmuyor, güzelce ötüyor.

Ses çalmak için Phonon kütüphanesini kullanıyorum. Fakat nedense Pardus’daki PyQt’de Phonon desteği yok. O yüzden Pardus için eğer Phonon kütüphanesini bulamazsa PyGame’e geçebilecek.

Guguk projesi ne yapıyor, her saat başı saat kadar ötüyor ve bir pencere çıkarıp size ‘Guguk!’ diyip saati söylüyor. Ayrıca guguklama işlemini durdurup susup oturmasını sağlayabilirsiniz.  Başlattığınızda siyah G harfi kırmızı oluyor ve çalışmaya başladığını haber veriyor.

Guguk projesini şuradan bulabilirsiniz.

Ve diğer süpriz:

Artık yazılarımın aynısı İngilizce olarak da bulabilrsiniz. Tamamen kendim çevirmeye çalıştım. Kelime kelime olmasa da anlamlarının aynı olduğundan emin olabilirsiniz.

Dil bölümünden dil değişikliği yapabilirsiniz.

27
Mar

Uğraştığım projelerimde genellikle yazdığım kütüphaneleri Python’un bulabilmesi bir zorluk haline geliyordu. Eğer  zorluk olmasın diye tüm kütüphanelerimi aynı klasöre atarsam o zaman da büyük bir karmaşa oluyordu. Ve karşıma “__init__.py” dosyası çıktı.

“__init__” adını Nesne Tabanlı Programlama yazımdan hatırlayacaksınız, orada bizim için nesnemizin parametrelerini tutan aynı zamanda belirlemeler yaptığımız bir tür içindekiler listesiydi. Şimdi ise “__init__.py” dosyası bizim için aynı işi görecek.

Diyelim ki ben matematik hesapları yaptırdığım bir projem var. Ve kütüphanelerim şöyle:

  • Kare için kare.py
  • Dikdörtgen içeren dikdortgen.py
  • Daire içeren daire.py
  • Küp içeren  kup.py
  • Prizmalar içeren prizma.py
  • Küre içeren kure.py

Ve biz elimizde bu tüm geometrik cisimleri 2 ve 3 boyut olmak üzere ayıralım. 2 boyutluları ikiboyut klasörüne koyalım, 3 boyutluları ucboyut klasörüne koyalım. Ve şimdi bu klasörlerin yanına “main.py”(başlangıç betiğimiz) oluşturduktan sonra dosyamızdan klasörlerden çağırmak için bu oluşturduğumuz iki klasörün içine “__init__.py” dosyayı oluşturalım ve içine hiçbir şey yazmalayalım.*

Şimdi main.py’dan “from ikiboyut.kup import *” ya da “import ucboyut.prizma as prizma” diyebiliriz. Böylece klasörlerin içinden kütüphanelerimizi rahatça çağırmış olduk.

Bu işin aynısını sys modülü ile yapabiliriz anca büyük bir karmaşa oluşabilir. Sys için ise “sys.path.append(os.getcwd()+”/ucboyut/”)” demeniz gerekiyor. Böylece başlangıç betiğiniz kütüphanelerinizi bulabilir.

Kısacası “__init__.py” ile klasörlerinizi bir kütüphane gibi düşünebilirsiniz. Kütüphanenin içindeki kütüphaneyi çağırıp, düzenli bir şekilde rahatça programınızı geliştirebilirsiniz.

Not*: Gördüğünüz üzere “__init__.py” dosyasını boş bıraktık. Eğer çok isterseniz belirlemelerinizi orada da yapabilirsiniz. “deneme = 10″ diyip, klasörün adından çağırdığınız da “import ucboyut.deneme as deneme”, “print deneme” size 10 diyerek geri dönecektir. İsterseniz nesne belirlemelerinizi de orada yapabilirsiniz.

30
Oca

Şu günlerde bazı açık kaynak projelerin kurulum dökümanlarına ve başlangıç betiklerine bakarken karşıma ‘glob’ isimli bir modül geldi. Meğerse ne şahane bir şeymiş, haberim yok. Efendim glob ile istediğiniz dosyaları uzantılarına göre dosya yakayalabiliyorsunuz. Nasıl mı ? Şöyle:

import glob
pdfdosya = glob.glob('/home/tdgunes/*.pdf')

ile pdf dosyalarınızı bulabilirsiniz. Eğer betiği çalıştırdığınız noktadaki dosyaları bulacaksanız yapmanız gereken

import glob, os
pdfdosya = glob.glob(os.getcwd() + '/*.pdf')

Kurulum betiklerinde genellikle .ui, .qrc gibi dosyaların derlenmesinden önce dosyaların bulunması için kullanılıyormuş. İsterseniz güzel bir betikle tüm diskteki .pdf dosyalarını da bulabilirsiniz.

Python ile dosya bulmakta böylece kolay oldu.

6
Kas

İnternet’ten Python öğrenenlerde genellikle bazı konular eksik kalabiliyor. Örneğin ‘Finally’ gibi. ‘Finally’, hata yakalarken yaptığınız işlemde son adım olarak ortaya çıkan verilerin temizlenmesi olarak kullanabileceğimiz kullanışlı bir komut. Klasik ‘try:’, ‘except:’ yazdıktan sonra ‘finally:’ koyabiliyoruz demek oluyor bu. Peki nasıl uyguluyoruz bir bakalım.

a = 10
try:
    a += "10"
except TypeError:
   print 'Tipler uyuşmadı.'
finally:
   print 'Veriler sıfırlanıyor'
   a = 0

‘finally’inin kullanımı böyle. Bu kodu tanımlarsak sırasıyla:

  1. Bir a değeri belirledik ve buna 10 dedik.
  2. Sonra bir de üstüne string(yazı) olan “10″ eklemeye çalıştık.
  3. Bunun sonucunda bir ‘TypeError’ aldık.
  4. Sonra a’yı sıfırladık.

Burada merak edeceğiniz mevzu eğer ‘TypeError’ oluşmasaydı ne olacağıydı. Eğer bu hata oluşmasaydı, veriler gene sıfırlanacaktı. Finally işlemini temizleme olarak görebilirsiniz. Ama çok isterseniz, bu ifadenin altına da temizleme komutunu yazabilirsiniz. Bu tercih size kalmış.

18
Eki

Nesne tabanlı programlamadan sonra bir başka merak ettiğim konu ise: Konsol tabanlı bir program yaptığımda ona verdiğim komutları, hep uzun uzun yazmam gerekiyordu. Mesela bir oyun yaptınız. Konsoldaki haritanızda ileri,geri,sağ ve sola gitmesi için durmadan “ileri,geri …” yazmanız gerekiyor.

Fakat artık direk “WASD” tuşları olsun klavyedeki her tuşla programa komutlar gönderebileceksiniz. Yapmanız gereken “tty” modülünü kullanmak fakat bu modül çok ilginç ki, programı kapattıktan sonra bile sizin klavye komutlarınızı alıyor.  Bunun yerine hem Linux, hem Windows, hem de Macintosh’larda çalışacak bir yöntem ve sadece “tty” modülüyle değil de başka modülleri de kullanmalı. Çünkü tty modülü sadece Linux’da çalışıyor ve stabil değil.

Küçük bir google araması yaptığınızda karşınıza şöyle bir site geliyor. (Macintosh desteğini denemediğim için örneklere yazmayacağım ama o siteden Macintosh desteğine bakabilirsiniz.)

İlk önce tane .py dosyası oluşturun ve onun içine şunları yazın.

# -*- coding: utf-8 -*-
class _Getch(object):
    """Gets a single character from standard input.
       Does not echo to the screen."""
    def __init__(self):
        try:
            self.impl = _GetchWindows()
        except ImportError:
            self.impl = _GetchUnix()
 
    def __call__(self):
        return self.impl()
 
class _GetchUnix(object):
    def __init__(self):
        import tty, sys
 
    def __call__(self):
        import sys, tty, termios
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch
 
class _GetchWindows(object):
    def __init__(self):
        import msvcrt
 
    def __call__(self):
        import msvcrt
        return msvcrt.getch()
 
getch = _Getch()

Bunu sonra ana programınıza “form dosyanız import *” şeklinde ekleyin. Sonra kullanırken:

from alici import *
while True:
    karakter = getch().upper()
    print "Tıklanan tuş: %s"  % karakter

şeklinde yazabilirsiniz. Burada “getch().upper()” yazarken “upper()” yazmamızdaki mantık, gelen karakterin büyük ya da küçük problemi yaşamamak için hepsini büyük yapıp öyle işlemektir.  Bu yazdığınız “.getch()” bu haliyle Linux’da ve Windows’da çalışabilir.

Ayrıca bu olay PyGame gibi başka kütüphanelerle yapılabilir fakat eğer tamamen konsol tabanlı bir programda bunu istiyorsanız tek çözüm bu.

Not: Son örnekteki döngüden kurtulamazsanız kurtarıcınız “CTRL-C” olsun.

8
Eki

Python’u ilk duyduğum da, Python’un nesne tabanlı olduğunu üstüne basa basa söylediler ama şu ana kadar uğraştığım birçok projede olsun, yazdığım kodların çoğunda olsun, “Ben bunu nesne tabanlı olsun diye yapıyorum.” diyerek yapmadım ve nesne tabanlı programlamayı da kullanmanın ne kadar büyük bir kolaylık getirdiğinin de farkında değilmişim.

Nesne tabanlı programlamayı basitçe, kendi dünyanıza ekleyeceğiniz nesnelerin yapım aracı olarak düşünebilirsiniz. Ben dünyamda kare istiyorum ve karemin alanı, çevresi belli olsun diyebilirsiniz. Eski bilgilerinizle böyle bir şey isteğiniz de fonksiyonlar yazıp, sonra çağırımlar yapabilirdiniz ama artık nesne tabanlı programlamayla, fonksiyon çağırımlarıyla uğraşmadan direk a = kare(2) (2 burada kenarın uzunluğu)” diyebilirsiniz.  Kafanızda “Nasıl olacak bu iş?” diye bir soru oluştuysa hadi bakalım nasıl oluyormuş.

Şu ana kadar sınıf(class) kullanmadıysanız sınıflara merhaba diyin. Eğer kullandıysanız, (Arayüz falan yazarken) belki de bilmeden kullandınız.(Tıpkı benim gibi :) ) Sınıflar nesneler üretmenin en güzel yoludur. Gelin bir kare nesnesinin sınıfını yazalım.

class kare():
    def __init__(self, kenar):
	self.kenar = kenar
    def cevresi(self):
        return self.kenar*4
    def alani(self):
        return self.kenar*self.kenar

Yaratığımız bu kare sınıfının en çok kafa karıştıran yeri “__init__” kısmı olabilir. Peki nedir “__init__” kısmı ? Basitçe burayı bir kitabın içindekiler bölümü olarak görebilirsiniz. Burada bizim kare için sadece “kenar” yerimiz var.  Bir başka soru neden “self.kenar = kenar” dediğimiz olabilir. self ile sınıf içinde fonksiyonlara ulaşmak için global gibi bir değer kullanmak yerine kolayca fonksiyonlar arasında bu değerleri kullanabiliyoruz.

Peki son olarak gelin a bir kare nesnesi olsun. Bunu yapmak için “raw_input” kullanabiliriz.

b = int(raw_input("Kare'nin kenarı kaç olsun? : "))
a = kare(b)

Bundan sonra yapacağımız kare sınıfındaki fonksiyonları çağırmak olacaktır.  Onu da şöyle halledebiliriz:

print "Çevresi: %s Alanı: %s" % (a.cevresi(), a.alani())

Kare cismimizi yaratarak nesne tabanlı programlama’yı az da olsa öğrenmiş olduk.

Not: Sınıfların içine yazdığımız fonksiyonlarda, __str__ adlı bir fonksiyon olduğunu ve bunla str(a) dediğinizde bir olayı başlatabileceğinizi biliyor muydunuz ? __str__ kısmını __int__ yapabilir ve daha birçok built_in fonksiyonlarla oynayabilirsiniz.

Python, Python, Python :)

9
Eyl

Python ile MySQL bağlantısı yaptık bakalım şimdi python ile nasıl .mp3 ve .midi dosyalarını dinleyebiliriz. Öncelikle yapmanız gereken pygame paketini Pardus deposundan indirmek. Neden pygame’i kullanıyoruz diye bir soru sorarsanız cevabım ise Pardus deposundaki bir paket olduğu ve ek olarak başka büyük kütüphaneleri kullanmayacağımızdır. Aslında .mp3 ve .midi dosyalarını açarken pygame yerine direk “os.system(“play dosyadi”) ” şeklinde bir komut da kullanabilirsiniz ama python içinden bu işi yapmak daha mantıklı olduğunu söylemeliyim.

PyGame modülünü edindikten sonra kod yazımına sıra geldi. Basitçe internetten nasıl yapabilirim diye kendime sorduğumda şu sitede aşağıdaki kodlar yer alıyordu.

 
# -*- coding: utf-8 -*-
import pygame
dosya = raw_input("Dosya adı:\n")
def baslat(dosya):
    clock = pygame.time.Clock()
    try:
	print "- Dosya yüklendi -"
        pygame.mixer.music.load(dosya) #dosyayı yükler
    except pygame.error:
        print "%s adlı dosya bulunamadı.\n(%s)" % (dosya, pygame.get_error())
        return
    pygame.mixer.music.play()
    while pygame.mixer.music.get_busy():
        clock.tick(30)
 
freq = 44100     # audio CD kalitesi
bitsize = -16    # 16 bit
channels = 2     # 1 mono, 2 stereo
buffer = 2048
pygame.mixer.init(freq, bitsize, channels, buffer)
# 0 'dan 1.0 kadar ses seviyesi
pygame.mixer.music.set_volume(0.75)
 
try:
    baslat(dosya)
except KeyboardInterrupt:
    # CTRL-C ile kapanırsa
    pygame.mixer.music.fadeout(1000)
    pygame.mixer.music.stop()
    raise SystemExit

Kodları sitedekine göre Türkçeleştirip, bir de “raw_input” ekledim. Ama arada bir bir daha programı açarsanız, bazen susmayı ve hata vermemeyi tercih edebiliyor.

İyi Pythonlamalar!