| |
| |
![]() |
![]() | | Konu Seçenekleri | ![]() |
| | #1 |
| Dekan Genç Kuvvet ![]() | Python Kılavuzu
Lisans bilgileri için http://www.python.org/2.2/license.html adresine bakınız. Python kolay öğrenilen güçlü bir programlama dilidir. Verimli yüksek seviyeli veri türlerine sahiptir ve nesne tabanlı programlamaya yaklaşımı basit ve etkilidir. Python'un şık sözdizimi, dinamik veri türleri ve yorumlanan bir dil oluşu onu çoğu alan ve platformda hızlı yazılım geliştirme için ideal yapar. Python yorumlayıcısı ve geniş standart kütüphanesi kaynak ya da çalıştırılabilir paket olarak Python Web sitesinden alınabilir ve dağıtılabilir. Aynı sitede farklı Python dağıtımları, modüller, programlar ve belgeler bulunabilir. Günümüzde yaygın olarak kullanılan işletim sistemlerinin çoğu için bir Python dağıtımı mevcuttur. Python yorumlayıcısı C veya C++ (ya da C dilinden çağırılabilen başka bir dil) ile yazılmış veri türleri ve işlevler ile genişletilebilir. Diğer dillerde yazdığınız programlarınıza da Python yorumlayıcısını bağlayabilir ve Python ile ek özellikler eklenebilen programlar yazabilirsiniz. Bu kılavuz okuyucuya Python dilinin temel özelliklerini, kavramlarını ve sistemini tanıtmaktadır. Örnekleri denemek için el altında bir Python yorumlayıcısı bulundurmak yararlı olur. Bu kılavuz Python'un bütün özeliklerini ya da yaygın olarak kullanılan her özelliğini açıklamak amacında değildir. Bunun yerine Python'un kayda değer özelliklerinin çoğu tanıtılmaktadır ve dilin tarzı ile ilgili iyi bir fikir verilmektedir. Bunu okuduktan sonra Python modülleri ve programlarını okuyup yazabileceğiniz gibi Python ile gelen geniş kütüphane ile ilgili daha çok şey öğrenmeye hazır olacaksınız. İştahınızı Kabartalım: Eğer büyük bir kabuk betiği yazdıysanız neler olduğunu bilirsiniz. Bir özellik daha eklemek istersiniz; ancak program yeterince büyük ve yavaş olmuştur ya da istediğiniz özelliğe sadece C aracılığıyla erişilebilir... Genellikle program C ile baştan yazılmaya değecek önemde değildir ya da kabukta kolay olduğu halde C'de zor elde edilen özellikleri vardır. Belki de C ile yeterince iyi değilsiniz. Bir diğer durum düşünün: birkaç C kütüphanesi ile çalışmanız gerekiyor ve normal yaz/derle/dene/tekrar derle döngüsü çok yavaş geliyor ve daha hızlı program yazmaya ihtiyacınız var. Belki de genişletilebilir bir program yazacaksınız; ancak bunun için yeni bir dil tasarlayıp bunun için gerekli yorumlayıcıyı yazıp programınıza ekleyeceksiniz. Bu gibi durumlarda Python tam aradığınız dil olabilir. Python kullanımı basit fakat gerçek bir dildir. Büyük programlar için kabuktan daha uygundur ve C'den çok daha fazla hata denetimi yapar. Python çok yüksek seviyeli bir dil olup C ile verimli şekilde yazılması günler alabilecek yüksek seviyeli veri türlerine sahiptir (sözlükler ve listeler gibi). Daha genel veri türleri sayesinde Python Awk hatta Perl'den çok daha geniş bir yelpazede uygulama alanı bulabilir. Ayrıca Python'da pek çok şey en az o dillerdeki kadar kolaydır. Python ile programlarınızı daha sonra diğer Python programlarınızda tekrar kullanabileceğiniz modüllere ayırabilirsiniz. Python geniş bir standart modül kolleksiyonu ile size gelmektedir. Dosya giriş/çıkışı, ses, resim, matematiksel işlemler vs. ile ilgili modüller de vardır. Python yorumlanan bir dil olduğu için program geliştirme sırasında size önemli miktarda zaman kazandırabilir. Çünkü derleme ve ilintileme gerekmemektedir. Yorumlayıcıyı etkileşimli olarak da kullanabilirsiniz; böylece dilin özelliklerini kolayca deneyebilir, hızlı bir şekilde küçük programlar yazabilir, ya da aşağıdan-yukarı program geliştirme sırasında işlevlerinizi test edebilirsiniz. Yorumlayıcı bir hesap makinesi olarak da kullanılabilir. Python ile son derece sıkı ve okunabilir programlar yazabilirsiniz. Birkaç nedenden Python programları eşdeğer C veya C++ programlarından çok daha kısadırlar: Yüksek seviyeli veri türleri ile karmaşık işlemler tek bir ifade ile yazılabilir. Deyimlerin gruplanması, başlama/bitme deyimleri (begin, end veya {} gibi) yerine blokların girintili yazılması ile sağlanır. Değişken veya argüman bildirimlerinin yapılması gerekmez. Python genişletilebilir: Eğer C programlamayı biliyorsanız Python'a kolayca yeni modüller ekleyebilir ya da programınızın hızlı çalışması gereken kısımlarını C ile yazabilirsiniz. C programlarınıza da Python yorumlayıcısını bağlayabilir ve Python ile ek özellikler eklenebilen programlar yazabilirsiniz. Python programlama dili adını korkunç bir sürüngenden değil, `Monty Python's Flying Circus'' adlı bir BBC komedi dizisinden almıştır. Öğrenmek İçin... Artık Python konusunda heyecanlandınız ve daha ayrıntılı olarak incelemek istiyorsunuz. Bir dili öğrenmenin en iyi yolu onu kullanmak olduğundan sizi Python kullanmaya davet ediyoruz. Bir sonraki bölümde yorumlayıcıyı kullanmayı öğreteceğiz. Bu çok basit bir şey; ancak daha sonraki bölümlerin anlaşılması için önemli. Kılavuzun devamında basit ifadeler, deyimler ve veri türleri ile başlayıp, işlevler ve modüllerden kullanıcı tanımlı sınıflar gibi gelişmiş konulara kadar Python'un çeşitli özellikleri örnekler ile anlatılmaktadır. Yorumlayıcının Çalıştırılması Python yorumlayıcısını Linux Konsolunda ya da xterm'de python komutunu girerek çalıştırabilirsiniz. Python yorumlayıcısının konsolda çalışanı olduğu gibi X Pencere Sisteminde çalışanı da vardır. X pencere sisteminde çalışan yorumlayıcı idle komutu ile çalıştırılabilir. Menüleriyle kolay kullanılabilen bir Python düzenleyicisidir ve konsolda çalışan python gibi "Python Kabuğu" penceresinde doğrudan komut icra edilebilir. python çalıştırıldığında yorumlayıcı konsolda etkileşimli kipte çalışır. Yorumlayıcı çalıştırılacak olan Python programının dosya adı parametre şeklinde verilerek de kullanılabilir. Örneğin python deneme.py gibi. Etkileşimli Kip Komutların yorumlayıcıya satır satır girildiği duruma etkileşimli kip denir. Bu kipte birincil komut satırı >>> şeklindeyken ikincil komut satırı ... şeklinde görülür. Örneğin: bash-2.05$ python Python 2.2.2 (#1, Feb 24 2003, 19:13:11) [GCC 3.2.2 20030222 (Red Hat Linux 3.2.2-4)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> Birden fazla satırlık bloklar girildiğinde satırlar ikincil komut satırında girintili yazılır: >>> dunya_duzdur=1 >>> if dunya_duzdur: ... print "Düşmemeye dikkat et!" ... Düşmemeye dikkat et! >>> Yorumlayıcıdan çıkmak için ctrl+D tuşlayın. Etkileşimli kipte çalıştırılan programlarda bir hata bulunması halinde yorumlayıcı bir hata mesajı basar ve birincil komut satırına döner: >>> if dunya_duzdur: ... print "Düşmemeye dikkat et!" File "<stdin>", line 2 print "Düşmemeye dikkat et!" ^ IndentationError: expected an indented block >>> Burada 2. satırın girintili yazılması gerektiği hatırlatılıyor. Ayrıca etkileşimli kipte ya da Python programlarınızı yazarken komut satırı yerine daha rahat bir ortamda calışmak isteyebilirsiniz. Bunun için Python ile birlikte gelen idle'ı deneyebilirsiniz. idle Python ile yazılmış bir uygulama. Bazı idle komutları şöyledir: Alt+p Yazdığınız bir önceki komutu getirir. Alt+n Yazdığınız bir sonraki komutu getirir. enter Yazdığınız komutları çalıştırır. Python Betikleri Kabuk betiklerine benzer şekilde Python betikleri de, dosyanın ilk satırına #! /usr/bin/env python yazılarak ve dosyaya çalıştırma izni verilerek (chmod +x dosya.py) doğrudan kabuktan çalıştırılabilirler Hataların Yakalanması Bir hata oluştuğunda yorumlayıcı bir hata mesajı ve hatalı noktaya gelmeden önce işletilen işlev çağrılarının listesini basar. Python'a Giriş Aşağıdaki örneklerde giriş ve çıkış, komut satırının varlığına veya yokluğuna (>>> veya ... ) bağlıdır. Örnekleri tekrar etmek için komut satırında görünen her şeyi yazmalısınız. >>> veya ... ile başlamayan bütün satırlar yorumlayıcı çıktısını temsil ederler. İkincil komut satırındaki boş bir satır (sadece "... ")) olan yerlerde bir şey yazmanıza gerek yok. O satırlar boş olup bir deyimler öbeğinin bitirilmesi için kullanılırlar. Bu kılavuzdaki alıştırmaların çoğu, etkileşimli komut satırına yazılanlar dahil, açıklamalar içerirler. Python dilinde açıklamalar "#" ile başlarlar ve bulundukları satır sonuna kadar devam ederler. Bir dizge içinde bulunan "#" işareti bir açıklama başlatmaz. Bu sadece bir "#" karakteridir. Örnekler: # Bu bir açıklama. SAYI = 1 # ve bu ikinci açıklama # ... bu da üçüncü! DIZGE = "# Bu bir açıklama değil." Python'u Hesap Makinesi Olarak Kullanmak Sayılar Şimdi bazı basit komutlar deneyelim. Yorumlayıcıyı çalıştırın ve birincil komut satırının gelmesini bekleyin. Yorumlayıcı basit bir hesap makinesi olarak iş görürebilir: istediğiniz herhangi bir ifadeyi yazın ve yorumlayıcı sonucu verecektir. İşleçler ( +,-,*,/ ) çoğu programlama dillerindekine benzer çalışır (Pascal ve C de olduğu gibi mesela). İfadeleri gruplamak için parantezler de kullanılabilir. Örnekler: >>> 2+2 4 >>> # Bu bir açıklama ... 2+2 4 >>> 2+2 # bu da komutlarla aynı satırda bir açıklama 4 >>> (50-5*6)/4 5 >>> # Tam sayı bölme işlemlerinde ise: ... 7/3 2 >>> 7/-3 -3 C'de olduğu gibi eşit işareti ( = ) bir değişkene değer atamak için kullanılır. Atamanın değeri çıkışta yazılmaz: >>> genislik = 20 >>> yukseklik = 5*9 >>> genislik * yukseklik 900 Bir değer aynı anda birden fazla değişkene atanabilir: >>> x = y = z = 5 # x, y ve z beş değerini alır >>> x 5 >>> y 5 >>> z 5 Tam gerçel sayı desteği vardır. Farklı türdeki değerlerin olduğu işlemlerde sonuç gerçel sayıya dönüştürülür: >>> 3 * 3.75 / 1.5 7.5 >>> 7.0 / 2 3.5 Karmaşık sayılar da desteklenmektedir. Sayıların sanal kısımları j veya J soneki ile yazılır. Gerçek kısmı sıfır olmayan karmaşık sayılar (gerçek + sanalj) şeklinde yazılırlar ya da complex(gerçek, sanal) işlevi ile kullanılırlar. >>> 1j * 1J (-1+0j) >>> 1j * complex(0,1) (-1+0j) >>> 3+1j*3 (3+3j) >>> (3+1j)*3 (9+3j) >>> (1+2j)/(1+1j) (1.5+0.5j) Karmaşık sayılar daima iki gerçel sayı ile ifade edilirler; biri gerçek diğer sanal kısım için. Z gibi bir karmaşık sayının gerçek ya da sanal kısımlarına erişmek için Z.real ve Z.imag kullanılır. a=1.5+0.5j >>> a.real 1.5 >>> a.imag 0.5 Tamsayı veya gerçel sayıya dönüştürme işlevleri (float(), int() ve long()) karmaşık sayılar için çalışmazlar; bir karmaşık sayıyı gerçek bir sayıya dönüştürmenin doğru bir yolu mevcut değildir. abs(z) ile karmaşık sayının büyüklüğünü ve z.real ile gerçek kısmını elde edebilirsiniz. >>> a=3.0+4.0j >>> float(a) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: can't convert complex to float; use e.g. abs(z) >>> a.real 3.0 >>> a.imag 4.0 >>> abs(a) # sqrt(a.real**2 + a.imag**2) 5.0 >>> Etkileşimli kipte son yazdırılan değer _ değişkenine atanır. Yani Python'u hesap makinesi olarak kullanırken bazen işlemlere şu şekilde devam etmek daha kolaydır : vergi= 17.5 / 100 >>> fiyat= 3.50 >>> fiyat * vergi 0.61249999999999993 >>> fiyat + _ 4.1124999999999998 >>> round(_, 2) 4.1100000000000003 >>> Bu değişken ( _ ) kullanıcı tarafından salt okunur olarak kabul edilmelidir. Buna kasıtlı olarak değer atamayın. Bu aynı isimli bir yerel değişken yaratır. Dizgeler Sayılara ek olarak, Python dizgeler üzerinde de işlemler yapabilir. Dizgeler farklı şekillerde ifade edilebilir. Tek veya çift tırnak işareti içine alınabilirler: >>> 'dizge' 'dizge' >>> "Python\'un gücü" "Python'un gücü" >>> "doesn't" "doesn't" >>> '"Yes," he said.' '"Yes," he said.' >>> "\"Yes,\" he said." '"Yes," he said.' >>> '"Isn\'t," she said.' '"Isn\'t," she said.' Dizgeler birkaç şekilde birden fazla satıra yayılabilirler. Yeni satırlar ters eğik çizgi ile şöyle gösterilebilirler: >>> merhaba = "Bu C de de kullandığınıza benzer\n\ ... birkaç satır kaplayan bir dizge.\n\ ... Bu satırın başındaki \ ... girintinin belirgin olduğuna \ ... dikkat edin\n" >>> print merhaba ve bu şu çıktıyı verir: Bu C de de kullandığınıza benzer birkaç satır kaplayan bir dizge. Bu satırın başındaki girintinin belirgin olduğuna dikkat edin >>> Karakter dizisini r ile imleyerek ham dizge yapacak olursak, \n\ karakterleri yorumlanmaz, dizgenin bir parçası haline gelirler. Örneğin: merhaba = r"Bu C de de kullandığınıza benzer\n\ birkaç satır kaplayan bir karakter dizisi." print merhaba şu çıktıyı verir: Bu C de de kullandığınıza benzer\n\ birkaç satır kaplayan bir karakter dizisi. Karakter dizileri bir çift üçlü tırnak içinde de gösterilebilirler: Dizgeler bir çift üçlü tırnak içinde de gösterilebilirler: """ veya '''. Bu gösterim şeklinde satır sonlarının \n ile gösterilmesine gerek yoktur ve onlar olmadan da yeni satırlar doğru şekilde görünürler. Örnek: print """ Kullanım şekli : seninprog [SEÇENEKLER] -y Bu yardım mesajını görüntüler -S bağlanılacak sunucu adı """ ifadesi şu çıktıyı verir : Kullanım şekli : seninprog [SEÇENEKLER] -y Bu yardım mesajını görüntüler -S bağlanılacak sunucu adı Yorumlayıcı dizge işlemlerinin sonucunu girişine yazıldığı şekli ile çıkışa yazar. Dizgeler + işleçi ile birleştirilip, * ile tekrarlanabilirler: kelime = 'Alo' + 'ooo' >>> kelime 'Aloooo' >>> '<' + kelime*5 + '>' '<AlooooAlooooAlooooAlooooAloooo>' Yan yana iki dizge değişkeni otomatik olarak birleştirilir yani yukarıdaki örnekteki ilk satır kelime = 'Alo' 'ooo' şeklinde de yazılabilirdi. Bu sadece iki dizge değişkeni ile olur. Keyfî dizgeler arasında olamaz: import string >>> 'str' 'ing' # <- Bu doğru 'string' >>> string.strip('str') + 'ing' # <- Bu da doğru 'string' >>> string.strip('str') 'ing' # <- Bu geçersız !!! File "<stdin>", line 1, in ? string.strip('str') 'ing' ^ SyntaxError: invalid syntax C'de olduğu gibi, Python'da da dizgeler indislenebilirler. Dizgenin ilk karakterinin indisi sıfırdır. Python'da ayrı bir karakter veri türü yoktur. Bir karakter tek karakterli bir dizgedir. Icon dilinde (70'li yıllarda Ralph ve Marge Griswold'ün geliştirdiği Pascal benzeri bir SNOBOL4 türevi) olduğu gibi dizgelerin bölümleri dilim gösterimi [ : ] ile ifade edilebilirler. >>> kelime[4] 'o' >>> kelime[0:2] 'Al' >>> kelime[2:4] 'oo' C dilinden farklı olarak, Python'da dizgeler değiştirilemezler. Bir dizgenin indislenen bir konumuna değer atamaya çalışmak hatadır: >>> kelime[0] = 'x' Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: object doesn't support item assignment >>> kelime[:1] = 'Splat' Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: object doesn't support slice assignment Yukarıdaki soruna elde edilmek istenen dizge için yeni bir karakter dizisi oluşturularak çözüm bulunabilir. Bu kolay ve etkilidir: 'x' + kelime[1:] 'xloooo' >>> 'Splat' + kelime[4] 'Splato' Dilimlerin varsayılan başlangıç ve bitiş değerleri oldukça kullanışlıdır. Başlangıç değeri yoksa sıfır kabul edilir ve eğer bitiş değeri yoksa dilimlenen dizgenin boyu kadar olduğu kabul edilir. Örnekler : >>> kelime[:2] # İlk iki karakter 'Al' >>> kelime[2:] # İlk iki karakter dışındaki karakterler 'oooo' s[:i] + s[i:] = s olup dilimleme işlemlerinin kullanışlı bir şeklidir. Örnek: >>> kelime[:2] + kelime[2:] 'Aloooo' >>> kelime[:3] + kelime[3:] 'Aloooo' Çok büyük veya küçük dilim aralıkları akıllıca ele alınır. Bitiş değeri büyük ise bunun boyu dizgenin boyuna eşit olur. Başlangıç değeri bitişten büyük ise boş bir dizge elde edilir. >>> kelime[1:100] 'loooo' >>> kelime[10:] '' >>> kelime[2:1] '' İndisler negatif sayılar da olabilirler. Bu durumda saymaya sağ taraftan başlanır. >>> kelime[-1] # Son karakter 'o' >>> kelime[-2] # Sondan ikinci 'o' >>> kelime[-2:] # Son iki karakter 'oo' >>> kelime[:-2] # Son iki karakter dışındaki karakterler 'Aloo' -0 ın 0 ile aynı olduğuna dikkat edin; yani yine soldan sayar! >>> kelime[-0] # (-0 = 0 olduğundan) 'A' Sınır dışındaki negatif dilim indisleri küçültülürler; fakat bunu dilim olmayan tek bir indis ile denemeyin: >>> kelime[-100:] 'Aloooo' >>> kelime[-10] # hata ! Traceback (most recent call last): File "<stdin>", line 1 IndexError: string index out of range Dilimlerin nasıl çalıştığını hatırlamanın en iyi yolu indislerin karakterler arasını işaret ettiğini düşünmektir; şu şekilde bu daha iyi görülebilir: +---+---+---+---+---+ | H | e | l | p | A | +---+---+---+---+---+ 0 1 2 3 4 5 -5 -4 -3 -2 -1 Negatif olmayan indisler için dilim boyu indisler arası fark kadardır. Örneğin kelime[1:3] diliminin boyu 2 dir. Yerleşik işlev len() bir dizgenin boyunu verir. >>> s = 'ArrestedDevelopmentZingalamaduni' >>> len(s) 32 Listeler Python'da diğer veri türlerini bir gruba almayı sağlayan birkaç bileşik veri türü vardır. Bunların en kullanışlı olanlarından biri listelerdir. Listeler kare parantez içinde virgül ile birbirinden ayrılmış değerlerden (eleman) oluşurlar. Liste elemanlarının aynı türden olması gerekmez. >>>a = ['salam', 'zeytin', 100, 1234] >>> a ['salam', 'zeytin', 100, 1234] Listeler de dizgeler gibi indislenebilir. İndisler sıfırdan başlar. Listeler dilimlenebilir, birleştirilebilir vs... >>> a[0] 'salam' >>> a[3] 1234 >>> a[-2] 100 >>> a[1:-1] ['salam',100] >>> a[:2] + ['yumurta', 2*2] ['salam','zeytin', 'yumurta', 4] >>> 3*a[:3] + ['Oley!'] ['salam', 'zeytin', 100, 'salam', 'zeytin', 100, 'salam', 'zeytin', 100, 'Oley!'] Değiştirilemez (mutable) olan dizgelerin aksine, listelerin her bir elemanı değiştirilebilir: >>> a ['salam', 'zeytin', 100, 1234] >>> a[2] = a[2] + 23 >>> a ['salam', 'zeytin', 123, 1234] Liste dilimlerine de atama yapılabilir ve bu listenin boyunu da değiştirilebilir. >>> # Bazı elemanları değiştir: ... a[0:2] = [1, 12] >>> a [1, 12, 123, 1234] >>> # Bazı elemanları sil: ... a[0:2] = [] >>> a [123, 1234] >>> # Listenin içine elemanlar ekle: ... a[1:1] = ['bletch', 'xyzzy'] >>> a [123, 'qwerty', 'xyzzy', 1234] >>> a[:0] = a # Listenin kopyasını listenin başına ekle >>> a [123, 'qwerty', 'xyzzy', 1234, 123, 'qwerty', 'xyzzy', 1234] Yerleşik işlev len() listeler ile de çalışır: >>> len(a) 8 İç içe listeler yaratılabilir. Örnek: >>> q = [2, 3] >>> p = [1, q, 4] # buradaki q üst satırda tanımlanan listedir >>> len(p) 3 >>> p[1] [2, 3] >>> p[1][0] 2 >>> p[1].append('xtra') # append daha sonra açıklanacak >>> p [1, [2, 3, 'xtra'], 4] >>> q [2, 3, 'xtra'] Programlamaya Doğru İlk Adımlar Tabii ki Python kullanarak iki ile ikiyi toplamaktan daha karmaşık işler yapabiliriz. Mesela bir Fibonacci serisini şöyle yazabiliriz: >>> # Fibonacci serisi: ... # iki elemanın toplamı bir sonraki elemanı verir ... a, b = 0, 1 >>> while b < 10: ... print b ... a, b = b, a+b ... 1 1 2 3 5 8 Bu örnekte birkaç yeni özellik gösterilmektedir: İlk satırda bir çoklu değer atama var; a ve b değişkenleri bir anda 0 ve 1 değerlerini alırlar. Bu özellik son satırda da kullanılmaktadır. Son satırda dikkat çeken bir diğer olay da ifadenin sağ kısmının soldan sağa doğru atama işlemlerinden önce hesaplandığıdır. while döngüsü, verilen koşul (burada: b < 10) doğru olduğu sürece tekrarlanır. Python'da, C'de olduğu gibi, sıfır dışındaki herhangi bir değer doğru ve sıfır yanlış kabul edilir. Koşul bir dizge veya liste de olabilir. Boyu sıfır olmayan her şey doğru iken, boş listeler, dizgeler, vs yanlış kabul edilirler. Üstteki örnekte basit bir kıyaslama işlemi var. Standart kıyaslama işlemleri C'de olduğu gibi yazılır: < (küçük), > (büyük), == (eşit), <= (küçük eşit), >= (büyük eşit), != (eşit değil). Döngü bloğu girinitli yazılmıştır. Girintili yazma Python'un ifadeleri gruplama yoludur. Etkileşimli kipte girintili bir öbek yazıldığı zaman boş bir satır ile sonlandırılmalıdır (çünkü yorumlayıcı yazmayı ne zaman bıraktığınızı bilemez). Grintili bir öbek içindeki her satırın aynı girinti miktarına sahip olması gerektiğine dikkat ediniz. Girintiler için boşluk veya sekme karakterleri kullanılabilir. print deyimi kendisine verilen ifadenin veya ifadelerin değerini yazar. Birden fazla ifade verilmesi durumunda bunlar aralarında boşluk ile yazılırlar: >>>i = 256*256 >>> print 'İşlemin sonucu:', i İşlemin sonucu: 65536 Sona eklenen bir virgül ise çıktı satırından sonra yeni satıra geçilmesini engeller: >>> a, b = 0, 1 >>> while b < 1000: ... print b, ... a, b = b, a+b ... 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 Akış Denetimi Bir önceki bölümde tanıtılan while deyiminin yanısıra Python'da diğer programlama dillerinde de bulunan genel akış denetim deyimleri (bazı farklarla birlikte) vardır. if Deyimi Belki de en iyi bilinen deyim türü if deyimidir. Örnek: >>> x = int(raw_input("Lütfen bir sayı girin: ")) >>> if x < 0: ... x = 0 ... print 'Negatif sayı sıfırlandı' ... elif x == 0: ... print 'Sıfır' ... elif x == 1: ... print 'Bir' ... else: ... print 'Birden büyük' ... Sıfır veya daha fazla elif deyimi olabilir, ve else deyimi seçimliktir. elif deyimi else if deyiminin kısaltılmışıdır ve aşırı girintileri engellemesi açısından faydalıdır. Bir if ... elif ... elif ... deyimleri dizisi diğer dillerde bulunan switch veya case deyimlerinin yerine kullanılabilir. for Deyimi for deyimi Pascal veya C dillerinde görülenden biraz farklıdır. Python'daki for deyimi herhangi bir sıranın (liste, dizge, vs.) elemanları üzerinde sırayla yinelenir. Örnek: >>> # Bazı dizgelerin boylarını ölçelim: ... a = ['kedi', 'pencere', 'kertenkele'] >>> for x in a: ... print x, len(x) ... kedi 4 pencere 7 kertenkele 10 Üzerinde yinelenilen sırada değişiklik yapmak güvenli değildir (bu sadece listelerde olabilir). Eğer böyle bir şey yapacaksanız bu iş için dilim gösterimi ile listenin bir kopyasını kullanabilirsiniz: >>> for x in a[:]: # tüm listenin bir kopyasını oluştur ... if len(x) > 8: a.insert(0, x) ... >>> a ['kertenkele', 'kedi', 'pencere', 'kertenkele'] range() işlevi Eğer bir sayı sırası üzerinde tekrarlamalar yapmak isterseniz, belirli bir sıraya göre üretilen sayılardan oluşan bir liste oluşturan range() yerleşik işlevini kullanabilirsiniz. Örnek: >>> range(10) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] Verilen bitiş noktası asla üretilen listenin bir parçası olmaz; range(10) ifadesi 10 elemanı olan bir liste oluşturur. Listenin başlayacağı sayıyı ve artış miktarını da belirlemek mümkündür. Artış miktarı negatif de olabilir. >>> range(5, 10) [5, 6, 7, 8, 9] >>> range(0, 10, 3) [0, 3, 6, 9] >>> range(-10, -100, -30) [-10, -40, -70] range() ve len() işlevlerini bir arada kullanarak da bir listenin elemanları üzerinde döngüler kurabilirsiniz: >>> a = ['Python', 'programlama', 'öğrenmek', 'çok', 'kolay !'] >>> for i in range(len(a)): ... print i, a ... 0 Python 1 programlama 2 öğrenmek 3 çok 4 kolay Döngülerde break, continue ve else Deyimleri break deyimi, C'de olduğu gibi, içinde kaldığı en küçük for veya while döngüsünden çıkılmasına ve döngü deyiminin tamamen sona ermesine neden olur. continue deyimi döngü içindeki diğer deyimlerin atlanıp bir sonraki yineleme işleminin başlamasına sebep olur. Döngülerde else ifadesi de kullanılabilir; else bloğu döngü bittiğinde (for için) veya devamlılık koşulu geçersiz olduğunda (while için) işletilir; fakat döngü break deyimi ile sona erdiyse işletilmez. Bunu asal sayılar bulan aşağıdaki örnekte görebilirsiniz: >>> for n in range(2, 10): ... for x in range(2, n): ... if n % x == 0: ... print n, 'asal sayı değil. çarpanlar:', x, '*', n/x ... break ... else: ... # çarpan bulunmadan döngü biter ise ... print n, 'asal sayıdır' ... 2 asal sayıdır 3 asal sayıdır 4 asal sayı değil. çarpanlar: 2 * 2 5 asal sayıdır 6 asal sayı değil. çarpanlar: 2 * 3 7 asal sayıdır 8 asal sayı değil. çarpanlar: 2 * 4 9 asal sayı değil. çarpanlar: 3 * 3 pass Deyimi pass deyimi hiçbir şey yapmaz. Python sözdizim kurallarına göre bir ifadenin gerekli olduğu, fakat programın bir şey yapması gerekmediği zaman kullanılabilir: >>> while 1: ... pass # klavyeden CTRL+C ile kesilene kadar sürer ... İşlev Tanımlama Herhangi bir değere kadar Fibonacci serisi yazan bir işlev yazalım: >>> def fib(n): # n'e kadar Fibonacci serisini yazdır ... "n'e kadar Fibonacci serisini yazdır" ... a, b = 0, 1 ... while b < n: ... print b, ... a, b = b, a+b ... >>> # Tanımladığımız işlevi çağıralım: ... fib(2000) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 def anahtar kelimesi bir işlev tanımını başlatır. Bu deyimden sonra bir işlev adı ve parantez içinde parametreler yazılır. İşlevin gövdesini oluşturan program satırları sonraki satırdan itibaren girintili olarak yazılırlar. İşlev gövdesinin ilk satırı bir dizge de olabilir; bu dizge işlevin belgelenmesinde kullanılır (docstring). İşlevlerin belgelenmesinde kullanılan dizgeleri (docstring) otomatik olarak çevrim içi ya da basılı belgeler oluşturmak için kullanan yazılımlar vardır. Ayrıca bazı geliştirme ortamları bunları program yazarken kolaylık sağlaması için etkileşimli olarak programcıya sunarlar. Yazdığınız işlevlere bunları eklemeyi bir alışkanlık haline getirmeniz faydalı olur. Bir işlevin çağrılması (çalıştırılması) bu işlevdeki yerel değişkenlerin olduğu bir simge tablosu oluşturur. İşlev içerisinde bütün değer atama işlemlerinde değerler yerel simge tablosuna kaydedilir. Bir değişkene başvuru durumunda ise önce yerel (local), sonra genel (global) ve en son yerleşik (built-in) simge tablosunda arama yapılır. Bu yüzden genel değişkenlere doğrudan değer atama yapılamaz (eğer global ifadesi içinde kullanılmamışlar ise); ancak bunlara başvuru yapılabilir (reference). İşlev çağırıldığında işlevin parametreleri yerel simge tablosuna eklenirler; yani parametreler işleve değeri ile çağrı (call by value) kullanılarak iletilirler (yani parametreye yapılan değişiklikler yereldir, çağıran işlevdeki argümanlarda bir değişme olmaz). [86] Bir işlev başka bir işlevi çağırdığında bu çağrı için yeni bir yerel simge tablosu oluşturulur. Bir işlev tanımı işlev adının yürürlükte olan simge tablosuna eklenmesine sebep olur. İşlevin adı yorurumlayıcı tarafından kullanıcı tanımlı işlev veri türü olarak tanınır. Bu değer başka bir isime atanabilir ve bu da bir işlev olarak kullanılabilir. Bu genel bir isim değiştirme yolu olabilir: >>> fib <function object at 10042ed0> >>> f = fib # f de fib işlevi olur >>> f(100) 1 1 2 3 5 8 13 21 34 55 89 fib'in bir işlev olmayıp bir yordam (procedure) olduğunu düşünebilirsiniz. Python'da yordamlar, çağıran işleve değer geri döndürmeyen işlevlerdir. Aslında yordamlar da bir değer geri döndürürler, ama bu sıkıcı bir konudur. Bu değere None denir ve yerleşik bir değişkendir. Yorumlayıcı yazılacak tek değer bu ise normalde None yazmaz. Bunu görmeyi çok istiyorsanız şunu deneyin: >>> print fib(0) None Fibonacci serisini yazdırmak yerine, bunu bir liste şeklinde geri döndüren işlev yazmak basittir: >>> def fib2(n): # n e kadar fibonacci serisi geri döndürür ... " n e kadar fibonacci serisi içeren liste geri döndürür" ... sonuc = [] ... a, b = 0, 1 ... while b < n: ... sonuc.append(b) # değeri listeye ekle ... a, b = b, a+b ... return sonuc ... >>> f100 = fib2(100) # işlevi çağır >>> f100 # sonucu yazdır [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] Bu örnekte de bazı yeni Python özelliklerini görüyoruz: return deyimi bir işlevden değer geri döndürür. Parametresi olmayan bir return deyimi None geri döndürür. Sona eren bir yordam (procedure) da None geri döndürür. sonuc.append(b) ifadesi sonuç liste nesnesinin bir yöntemini çağırmaktadır. Bir yöntem bir nesneye `ait olan' ve nesne.yöntemAdı şeklinde adlandırılan bir işlevdir. nesne.yöntemAdı ifadesinde nesne herhangi bir nesne (bir ifade de olabilir) ve yöntemAdı da nesnenin türüne bağlı bir yöntemdir. Farklı veri türleri farklı yöntemlere sahiptirler. Farklı veri türlerinin ayni isimli yöntemleri olabilir. Sonraki bölümlerde anlatılacağı gibi, kendi veri türlerinizi ve yöntemlerinizi oluşturmanız mümkündür. Yukarıdaki örnekte görülen append() yöntemi liste nesneleri için tanımlıdır ve bir listenin sonuna yeni elemanlar ekler. Bu örnekte bu sonuc = sonuc + ifadesinin yaptığını yapar; ancak daha verimlidir. -------------------------------------------------------------------------------- [86] Aslında nesne başvurusu ile çağrı daha iyi bir tanım olur, çünkü işleve değiştirilebilir bir nesne aktarılırsa çağıran çağrılanın o nesneye uyguladığı tüm değişiklikleri görür (listeye eklenen elemanlar gibi). İşlev Tanımları Üzerine Daha Fazla Bilgi Değişken sayıda argüman alan işlevler tanımlamak da mümkündür. Bunun için kullanılan üç yöntem olup bunlar birleştirilerek kullanılabilir. Argüman Değerlerini Önceden Belirleme İşlev argümanlarına öntanımlı değerler atamak da mümkündür. Böylece çağıran işlev bu argümanları sağlamazsa bunlar önceden belirlenmiş öntanımlı değerlerini alırlar. Örnek: def onay_al(prompt, denemeler=4, sikayet='Evet veya hayır, lütfen !'): while True: ok = raw_input(prompt) if ok in ('e', 'evet'): return 1 if ok in ('h', 'hayır'): return 0 denemeler = denemeler - 1 if denemeler < 0: raise IOError, 'kararsız kullanıcı' print sikayet Bu işlev onay_al('Programdan çıkmak istiyor musunuz?') ya da onay_al('Dosyayı silmek istiyor musunuz?', 2) şeklinde çağırılabilir. İşlevin öntanımlı parametreleri işlevin tanımlandığı anda, o an yürürlükte olan etki alanı (scope) içinde değerlendirilirler. Yani: i = 7 def f(arg = i): print arg i = 6 f() 7 Uyarı İşlevin öntanımlı parametreleri sadece bir defa değerlendirilirler. Bu durum parametrenin liste gibi değiştirilebilir bir nesne olduğu durumlarda farklılık yaratır. Örneğin aşağıdaki işlev ard arda çağırıldığında argümanlarını biriktirir: def f(a, L = []): L.append(a) return L print f(1) print f(2) print f(3) Bu şu çıktıyı verir: [1] [1, 2] [1, 2, 3] Eğer öntanımlı parametre değerlerinin birbirini izleyen çağrılarla paylaşılmasını istemiyorsanız yukarıdaki işlevi şu şekilde yazabilirsiniz: def f(a, L = None): if L is None: L = [] L.append(a) return L Anahtar Kelime Argümanlar İşlevler anahtar kelime = değer şeklindeki anahtar kelimelerle de çağırılabililer. Örneğin şu işlev: def otomobil(yakit, hareket=' uçar', model='Anadol'): print "Eğer", yakit, "koyarsan bu", model, hareket aşağıdaki gibi çağırılabilir: otomobil('roket yakıtı') otomobil(hareket = 'dans eder', yakıt = 'zeytin yağı' ) otomobil('ispirto', model = 'Kartal') otomobil('su','bozulur','Şahin') Şu çağrılar ise hatalıdır: otomobil() # gerekli argüman eksik otomobil(yakıt = 'su','zeytin yağı') # anahtar kelimeden sonra gelen # anahtar kelime olmayan argüman otomobil('mazot', yakit = 'benzin') # aynı argüman için iki değer otomobil(sehir = 'İzmir') # bilinmeyen anahtar kelime Genel olarak, argüman listesinin başında konuma bağlı argümanlar bulunur ve anahtar kelime argümanlar onları izler; anahtar kelime adları da işlevin parametrelerinden seçilir. Parametrenin öntanımlı değerlerinin olup olmaması önemli değildir. Bir argüman birden fazla değer alamaz; konuma bağlı parametre isimleri aynı çağrıda anahtar kelime olarak kullanılamazlar. İşte bundan dolayı hatalı olan bir örnek: >>> def function(a): ... pass ... >>> function(0, a=0) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: keyword parameter redefined Eğer işlev tanımındaki son parametre **isim şeklinde ise bu parametre adları herhangi bir parametre olmayan anahtar kelime şeklindeki argümanların bulunduğu bir sözlük olur. Bu *isim (bu konu Sözlükler (Çağrışımlı Listeler) bölümünde anlatılacaktır.) şeklindeki bir parametre ile de kullanılabilir, ki bu parametre listesi içinde bulunmayan konuma bağlı argümanları içeren bir demet (daha sonra Demetler (tuples) bölümünde incelenecek bir veri türüdür) olur. *isim parametresi **isim parametresinden önce gelmelidir. Buna örnek işlev: def kasapdukkani(etCinsi,*argumanlar, **anahtarKelimeler): print "--", etCinsi, "var mi ?" print "-- Maalesef", etCinsi, "kalmadı." for arg in argumanlar: print arg print '-'*40 anahtarlar = anahtarKelimeler.keys() anahtarlar.sort() for ak in anahtarlar: print ak, ':', anahtarKelimeler[ak] Şu şekilde çağrılabilir: kasapdukkani('martı eti',"Çok lezzetli.", "Çok satılıyor.", musteri = 'Martı Murat', kasap = 'Dev İsmail') ve doğal olarak şu çıktıyı verir: -- martı eti var mi ? -- Maalesef martı eti kalmadı. Çok lezzetli. Çok satılıyor. ---------------------------------------- kasap : Dev İsmail musteri : Martı Murat anahtarKelimeler isimli sözlüğün içeriği yazdırılmadan önce anahtar kelime isimleri listesinin sort() yönteminin çağırıldığına dikkat edin; bu yapılmaz ise argümanların hangi sıra ile yazılacağı tanımlanmamış olur. Keyfî Argüman Listeleri Son olarak, en ender kullanılan seçenek de keyfî sayıdaki argümanla çağrılabilen bir işlev tanımlamaktır. Bu argümanlar bir demet (değişmez liste [tuple]) içine alınırlar. Keyfî argüman listesinden önce sıfır ya da daha fazla normal argüman bulunabilir. Örnek: def fprintf(file, format, *args): file.write(format % args) Lambda Biçemli İşlevler Yoğun istek üzerine işlevsel dillerde ve Lisp'te bulunan bazı özellikler Python'a eklenmiştir. lambda anahtar kelimesi ile küçük anonim işlevler yazılabilir. İşte iki argümanının toplamını geri döndüren bir işlev: lambda a, b: a+b. Lambda işlevleri bir işlev nesnesine ihtiyaç duyulan her yerde kullanılabilirler. Sözdizim (syntax) açısından bunlar tek bir ifade ile sınırlandırılmışlardır. Anlambilim (semantics) açısından ise normal işlev tanımlamasına getirilen bir sözdizim güzelliğidir. İç içe tanımlanmış işlevlerde olduğu gibi lambda işlevleri de kendilerini kapsayan etki alanindaki değişkenlere erişebilirler: >>> def artirici_yap(n): ... return lambda x: x + n ... >>> f = artirici_yap(42) >>> f(0) 42 >>> f(1) 43 Belgelendirme Dizgeleri Belgelendirmede kullanılan dizgelerin şekli ve içeriği ile ilgili şartlar yeni yeni oluşmaktadır. İlk satır daima nesnenin amacının kısa ve öz tanımı olmalıdır. Kısa olması için, nesnenin adından ve türünden bahsedilmemeli; zira bunlar başka yollarla da öğrenilebilir. Bu satır büyük harf ile başlayıp nokta ile bitmelidir. Eğer belgelendirme dizgesinde birden fazla satır var ise ikinci satır boş olup özet ile açıklamamın devamını birbirinden ayırmalıdır. Diğer satırlar bir ya da daha fazla satır olabilir. Bunlarla nesnenin özellikleri, çağrı şekilleri, yan etkileri vs. açıklanabilir. Python çözümleyicisi (parser) çok satırlı dizgelerdeki girintileri yok etmez; yani belgeleri işleyen programlar gerekirse bunları atabilirler. İlk satırdan sonra gelen ve boş olmayan ilk satırdaki girinti miktarı belgelendirme dizgesinin devamındaki girinti miktarını belirler. Bu girinti miktarına ``eşdeğer'' boşluk diğer satırların başından atılır. Daha az girintili satırlar olmamalı; ama olursa da bunların önündeki boşluğun tamamı atılmalı. Boşluğun eşdeğerliği sekmelerin genişletilmesinden (1 sekme = 8 boşluk) sonra sınanmalıdır. İşte çok satırlı bir belgelendirme dizgesi örneği: >>> def benimFonksiyon(): ... """Sadece belgeler. ... ... Başka birşey yapmaz. Gerçekten !. ... """ ... pass ... >>> print benimFonksiyon.__doc__ Sadece belgeler. Başka birşey yapmaz. Gerçekten ! Veriyapilari, Listeler Üzerine Daha Fazla Bilgi Liste veri türünün birkaç yöntemi daha var. İşte liste nesnelerinin bütün yöntemleri: append(x) Listenin sonuna bir eleman ekler; a[len(a):] = [x] ifadesine denktir. extend(L) Listeyi verilen listedeki tüm elemanarı ekleyerek genişletir; a[len(a):] = L ifadesine denktir. insert(i, x) Belirtilen konuma bir eleman yerleştirir. İlk argüman elemanın yerleştirileceği indistir. a.insert(0, x) ifadesi x'i listenin başına yerleştirir, ve a.insert(len(a), x) ifadesi a.append(x) ifadesine denktir. remove(x) Liste içinde değeri x olan ilk elemanı listeden siler. Böyle bir öğe yok ise bu hatadır. pop() Belirtilen konumdaki elemanı listeden siler ve bunu geri döndürür. Eğer bir indis belirtilmediyse, a.pop() listedeki son elemanı siler ve geri döndürür. (i etrafındaki köşeli ayraçlar bu parametreanin seçimlik olduğunu belirtir. Bu yazım biçimini Python belgelerinde sıkça görebilirsiniz.) index(x) Değeri x olan elemanın indisini geri döndürür. Böyle bir eleman yok ise bu hatadır. count(x) x'in listede kaç adet bulunduğunu bulur ve bu değeri geri döndürür. sort() Listenin elemanlarını sıralar - yerinde. reverse() Listenin sırasını tersine çevirir - yerinde. Liste yöntemlerinin çoğunu kullanan bir örnek: >>> a = [66.6, 333, 333, 1, 1234.5] >>> print a.count(333), a.count(66.6), a.count('x') 2 1 0 >>> a.insert(2, -1) >>> a.append(333) >>> a [66.6, 333, -1, 333, 1, 1234.5, 333] >>> a.index(333) 1 >>> a.remove(333) >>> a [66.6, -1, 333, 1, 1234.5, 333] >>> a.reverse() >>> a [333, 1234.5, 1, 333, -1, 66.6] >>> a.sort() >>> a [-1, 1, 66.6, 333, 333, 1234.5] Listelerin Yığın Olarak Kullanılması Liste yöntemleri listelerin kolayca yığın olarak kullanılmasını sağlarlar. Yığına son giren eleman ilk çıkar. Yığının üzerine eleman eklemek için append() ve en üstteki elemanı almak için indis belirtmeden pop() kullanılır. Örnek: >>> yigin = [3, 4, 5] >>> yigin.append(6) >>> yigin.append(7) >>> yigin [3, 4, 5, 6, 7] >>> yigin.pop() 7 >>> yigin [3, 4, 5, 6] >>> yigin.pop() 6 >>> yigin.pop() 5 >>> yigin [3, 4] Listelerin Kuyruk Olarak Kullanılması Listeleri kuyruk olarak da kullanmak mümkün. Bir kuyrukta ilk eklenen eleman ilk alınan elemandır (ilk giren ilk çıkar). Kuyruğun sonuna bir eleman eklemek için append() kullanılır. Sıranın başından bir eleman almak için ise 0 indisi ile pop() kullanılır. Örnek: >>> kuyruk = ["Ali", "Veli", "Deli"] >>> kuyruk.append("Küpeli") # Küpeli kuyrukta >>> kuyruk.append("Aylin") # Aylin kuyrukta >>> kuyruk.pop(0) 'Ali' >>> kuyruk.pop(0) 'Veli' >>> kuyruk ['Deli', 'Küpeli', 'Aylin'] İşlevsel Yazılım Geliştirme Araçları Listelerle kullanıldığında çok faydalı olan yerleşik işlevler vardır: filter(), map(), ve reduce(). filter(işlev, sıra) sıra içerisinden işlev(eleman)'ın doğru sonuç verdiği elemanların bulunduğu (mümkünse aynı türden) bir sıra geri döndürür. Örneğin, bazı asal sayıları hesaplamak için şöyle yapılabilir: >>> def f(x): return x % 2 != 0 and x % 3 != 0 ... >>> filter(f, range(2, 25)) [5, 7, 11, 13, 17, 19, 23] map(işlev, sıra) sıranın her elemanı için işlev(sıra) çağırır ve geri döndürülen değerlerin oluşturduğu listeyi geri döndürür. Örneğin bazı sayıların küplerini hesaplamak için şu yol izlenebilir: >>> def cube(x): return x*x*x ... >>> map(cube, range(1, 11)) [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000] map(işlev, sıra) ifadesinde birden fazla sıra da kullanılabilir; ancak bu durumda işlev sıra sayısı kadar argümana sahip olmalıdır. işlev her sıranın uygun elemanını bir argüman olarak alır; ancak sıralardan biri kısa ise eksik elemanlar için işleve None argümanı geçirilir. Eğer işlev adı için de None kullanılırsa argümanlarını geri döndüren bir işlev etkisi yaratılır. Bu iki özel durumu birleştirerek map(None, list1, list2) ifadesi ile bir çift diziyi çiftlerden oluşan bir diziye çevirebiliriz. Örnek: >>> sira = range(8) >>> def kare(x): return x*x ... >>> map(None, sira, map(kare, sira)) [(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25), (6, 36), (7, 49)] reduce(işlev, sıra) ifadesi tek bir değer geri döndürür. Bu değer şöyle elde edilir: iki argümanlı işleve sıranın ilk iki elemanı argüman olarak verilir, sonra da elde edilen sonuç ile sıranın sonraki elemanı argüman olarak verilir, daha sonra yine elde edilen sonuç ile bir sonraki eleman işleve verilir ve bu işlem bütün elemanlar için tekrarlanır. Örneğin 1'den 10'a kadar olanlar böyle toplanabilir: >>> def topla(x,y): return x+y ... >>> reduce(topla, range(1, 11)) 55 Sırada sadece bir eleman var ise bunun değeri geri döndürülür; sıra boş ise bir istisna oluşur (exception). Başlangıç değerini bildirmek için üçüncü bir argüman kullanılabilir. Bu durumda işleve ilk olarak başlangıç değeri ve sıranın ilk elemanına uygulanır ve diğer elemanlar ile devam eder. Örnek: >>> def sonuc(sira): ... def topla(x,y): return x+y ... return reduce(topla, sira, 0) ... >>> sonuc(range(1, 11)) 55 >>> sonuc([]) 0 Liste Üreteçleri Liste üreteçleri map(), filter() ve/veya lambda işlevlerini kullanmadan liste yaratmanın kısa bir yoludur. Bu yolla yaratılan liste tanımı genellikle daha kolay anlaşılır olur. Bir liste üreteci bir ifade ve bir for döngüsü ile bunları izleyen sıfır ya da daha fazla for veya if ifadelerinden oluşur. Sonuç kendisini izleyen for ve if bağlamında değerlendirilen ifadeden oluşan bir listedir. Eğer ifade bir demete (değişmez liste [tuple]) dönüşecekse parantez içinde yazılmalıdır. >>> freshfruit = [' banana', ' loganberry ', 'passion fruit '] >>> [weapon.strip() for weapon in freshfruit] # elemanları saran boşlukların atıldığı yeni bir liste ['banana', 'loganberry', 'passion fruit'] >>> vec = [2, 4, 6] >>> [3*x for x in vec] [6, 12, 18] >>> [3*x for x in vec if x > 3] [12, 18] >>> [3*x for x in vec if x < 2] [] >>> [{x: x**2} for x in vec] # sözlüklerden oluşan bir liste [{2: 4}, {4: 16}, {6: 36}] >>> [[x,x**2] for x in vec] [[2, 4], [4, 16], [6, 36]] >>> [x, x**2 for x in vec] # hata - demet için parantez gerekir File "<stdin>", line 1, in ? [x, x**2 for x in vec] ^ SyntaxError: invalid syntax >>> [(x, x**2) for x in vec] [(2, 4), (4, 16), (6, 36)] >>> vec1 = [2, 4, 6] >>> vec2 = [4, 3, -9] >>> [x*y for x in vec1 for y in vec2] [8, 6, -18, 16, 12, -36, 24, 18, -54] >>> [x+y for x in vec1 for y in vec2] [6, 5, -7, 8, 7, -5, 10, 9, -3] >>> [vec1*vec2 for i in range(len(vec1))] [8, 12, -54] Liste üreteçlerinin for döngülerine benzer davranması için, döngü değişkenine yapılan atamalar üreteç dışında da görünürler: >>> x = 100 # bu değişecek >>> [x**3 for x in range(5)] [0, 1, 8, 27, 64] >>> x 4 # range(5) için son değer >> del Deyimi del deyimi ile bir listeden indisi verilen bir eleman silinebilir. Bu deyim ile bir listeden dilimler de silinebilir (bunu daha önce dilimlere boş bir liste atayarak yapmıştık). Örnek: >>> a [-1, 1, 66.6, 333, 333, 1234.5] >>> del a[0] >>> a [1, 66.6, 333, 333, 1234.5] >>> del a[2:4] >>> a [1, 66.6, 1234.5] del deyimi tamamen silmek için de kullanılabilir: >>> del a Bu aşamadan sonra a ismine başvuru bir hatadır (aynı isme başka bir değer atanana kadar). Daha sonra del için başka kullanım alanları da göreceğiz. Demetler (tuples) Listelerin ve dizgelerin indisleme ve dilimleme gibi pek çok ortak özellikleri olduğunu grdük. Bunlar sıra şeklindeki iki veri türüdürler. Python gelişmekte olan bir dil; diğer sıra şeklindeki veri türleri de Python'a eklenebilir. Demet de başka bir sıra şekilli standart veri türüdür. Bir demet virgül ile ayrılmış bir kaç değerden oluşur. >>> t = 12345, 54321, 'merhaba!' >>> t[0] 12345 >>> t (12345, 54321, 'merhaba!') >>> # demetler iç içe kullanılabilirler : ... u = t, (1, 2, 3, 4, 5) >>> u ((12345, 54321, 'merhaba!'), (1, 2, 3, 4, 5)) Gördüğünüz gibi çıktıda demetler daima parantez içinde görünürler; ki iç içe geçmiş demetler belli olsun. Demetler parantezli veya parantezsiz olarak yazılabilirler; ancak parantezler genelikle gereklidirler (özellikle de demet daha büyük bir ifadenin içinde geçiyorsa). Demetlerin pekçok kullanım alanı var: (x, y) koordinat çifti, veri tabanındaki işçi kayıtları vb. gibi. Demetler de dizgeler gibi değerleri değiştirilemez veri türleridir; bunların elemanlarına atama yapılamaz (fakat dilimleme ve birleştirme aracılığı ile bu etki sağlanabilir). Ayrıca değiştirilebilen elemanlardan oluşan demetler oluşturmak da mümkündür (örnek: listelerden oluşan bir demet). Sıfır veya bir elemanlı demetlerin oluşturulması ile ilgili özel bir problem var: bunların ifade edilmesini sağlayan sözdizim biraz acayip. Boş demetler bir çift boş parantez ile ifade edilir. Tek elemanı olan bir demet için ise elemandan sonra bir virgül kullanılır (tek bir değeri parantez içine almak yeterli değildir). Çirkin ama etkili. Örnek: >>> bos = () >>> tekOge = 'merhaba', # <--satır sonundaki virgüle dikkat >>> len(bos) 0 >>> len(tekOge) 1 >>> tekOge ('merhaba',) t = 12345, 54321, 'merhaba!' ifadesi demetleme (tuple packing) işlemine bir örnektir: 12345, 54321 ve 'merhaba!' değerleri bir demet içinde toplanmışlardır. Bu işlemin tersi de mümkün: >>> x, y, z = t Doğal olarak, buna demet açma (sequence unpacking) deniyor. Demet açma sol taraftaki değişken sayısının sıra içindeki öğe sayısına eşit olmasını gerektirir. Çoklu değer atama işleminin aslında demetleme ve demet açmanın bir bileşimi olduğuna dikkat edin. Burada küçük bir asimetri var: birden fazla değeri demetleme her zaman bir demet oluşturur ve demet açma herhangi bir sıra için yapılabilir. Örnek: >>> paket = 'xyz' # bir dizge >>> a,b,c = paket >>> a 'x' >>> b 'y' >>> c 'z' Sözlükler (Çağrışımlı Listeler) Python'da bulunan bir diğer faydalı veri türü de sözlüktür. Sözlükler diğer programlama dillerinde ``çağrışımlı bellek'' (associative memory) veya ``çağrışımlı dizi'' (associative array) olarak bilinirler. Sayılarla indislenen sıralardan farklı olarak, sözlükler anahtarlar (key) ile indislenirler. Anahtar değiştirilemeyen türdeki herhangi bir veri türünde olabilir. Sayılar ve dizgeler her zaman anahtar olabilirler. Demetler de sayılar, dizgeler veya demetler içerdikleri sürece anahtar olabilirler. Bir demet doğrudan ya da dolaylı olarak değiştirilebilir bir nesne içeriyorsa anahtar olarak kullanılamaz. Listeler anahtar olamazlar, çünkü append() ile extend() yöntemleri, dilimleme ve indise değer atama ile değiştirilebilirler. Bir sözlük anahtar : değer çiftlerinden oluşur. Bir anahtar sözlükte sadece bir defa bulunabilir. Bir çift çengelli parantez boş bir sözlük yaratır : {}. Çengelli parantezlerin içine virgülle ayrılmış anahtar : değer çiftleri koymak anahtar ve değer çiftlerine ilk değerlerini verir. Çıktıya da sözlükler aynı şekilde yazılırlar. Sözlüklerle ilgili ana işlemler bir değerin bir anahtar ile saklanması ve anahtar verildiğinde değerin bulunmasıdır. del kullanarak bir anahtar : değer çiftini silmek mümkündür. Zaten mevcut olan bir anahtar kullanarak bir değer eklerseniz bu anahtarla bağlantılı eski değer unutulur. Mevcut olmayan bir anahtar ile değer istemek hatalıdır. Sözlük nesnesinin keys() yöntemi listedeki bütün anahtarların listesini rasgele sıralı olarak geri döndürür (sıralamak isterseniz listenin sort() yönteminden faydalanabilirsiniz). Bir anahtarın sözlükte olup olmadığını görmek için sözlüğün has_key() yöntemi kullanılır. İşte sözlük kullanan küçük bir örnek: >>> tel = {'jack': 4098, 'sape': 4139} >>> tel['guido'] = 4127 >>> tel {'sape': 4139, 'guido': 4127, 'jack': 4098} >>> tel['jack'] 4098 >>> del tel['sape'] >>> tel['irv'] = 4127 >>> tel {'guido': 4127, 'irv': 4127, 'jack': 4098} >>> tel.keys() ['guido', 'irv', 'jack'] >>> tel.has_key('guido') 1 dict() işlevi anahtar-değer çiftlerinden oluşan demetlerden sözlükler üretir. Çiftlerin bir kalıba uyduğu durumlarda, liste üreteçleri ile anahtar-değer çiftleri kısaca ifade edilebilir. >>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)]) {'sape': 4139, 'jack': 4098, 'guido': 4127} >>> dict([(x, x**2) for x in vec]) # liste üreteci kullanarak {2: 4, 4: 16, 6: 36} Döngü Teknikleri Sözlükler üzerinde döngüler kurarken o anki değer items() yöntemi ile aynı anda elde edilebilir. >>> knights = {'gallahad': 'the pure', 'robin': 'the brave'} >>> for k, v in knights.items(): ... print k, v ... gallahad the pure robin the brave Bir sıra üzerinde dönerken konum indisi ve ona karşılık gelen değer de enumerate() işlevini kullanarak aynı anda elde edilebilir. >>> for i, v in enumerate(['tic', 'tac', 'toe']): ... print i, v ... 0 tic 1 tac 2 toe Aynı anda iki sıra üzerinde ilerlemek için ise zip() işlevi ile bunlar çiftler haline getirilebilir. >>> sorular = ['adın', 'görevin', 'favori rengin'] >>> cevaplar = ['Adnan', 'Uyumak', 'Mavi'] >>> for s, c in zip(sorular, cevaplar): ... print 'Senin %s ne? %s.' % (s, c) ... Senin adın ne? Adnan. Senin görevin ne? Uyumak. Senin favori rengin ne? Mavi. Koşullu İfadeler Üzerine Daha Fazla Bilgi while ve if deyimlerinde kıyaslama dışında da işleçler kullanılabilir. in ve not kıyaslama işleçleri bir değerin bir sıra içinde olup olmadığını sınarlar. is ve is not işleçleri iki nesnenin tamamen aynı nesne olup olmadıklarını sınarlar (bu sadece liste gibi değiştirilebilir nesnelerde önemlidir). Bütün kıyaslama işleçleri aynı önceliğe sahiptirler ve bu sayısal işleçlerinkinden düşüktür. Kıyaslamalar zincirlenebilir: a < b == c gibi. Kıyaslamalar mantıksal işleçler and ve or ile birleştirilebilirler ve kıyaslamanın sonucu (ya da herhangi bir mantıksal ifade) not ile değillenebilirler. Bunların hepsi de kıyaslama işleçlerinden düşük önceliğe sahiptirler ve aralarında en yüksek öncelikli olan not ve en düşük öncelikli olan or işleçidir. Örneğin A and not B or C ifadesi (A and (not B)) or C ifadesine eştir. İstenen bileşimi elde etmek için parantezler kullanılabilir. and ve or mantıksal işleçlerine kısa devre işleç de denir. Bunların argümanları soldan sağa değerlendirilir ve sonuç belli olur olmaz değerlendirme işlemi kesilir. Örneğin A ve C doğru, fakat B yanlış olsun. A and B and C ifadesinde C ifadesi değerlendirilmez (çünkü C'nin değeri sonucu değiştirmez). Genel olarak bir kısa devre işleçi Bool değil de genel bir değer gibi kullanıldığında en son değerlendirilen argümanın değeri geri döndürülür. Bir kıyaslamanın ya da mantıksal ifadenin sonucunu bir değişkene atamak mümkündür: >>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance' >>> non_null = string1 or string2 or string3 >>> non_null 'Trondheim' C dilinin tersine, Python'da ifadelerin içinde atama olamayacağına dikkat edin. C programcıları bundan şikayetçi olabilirler; ancak bu C programlarında sık karşılaşılan bazı hataları engellemektedir (== yerine = yazmak gibi). Listeler, Dizgeler ve Demetler Arasında Kıyaslama Sıra nesneleri yine sıra şeklindeki diğer nesnelerle kıyaslanabilirler. Önce ilk iki eleman kıyaslanır. Bunlar farklı ise sonuç belli olmuştur; eşit olmaları halinde sonraki iki eleman kıyaslanır ve sıralardan biri tükenene kadar bu işlem tekrarlanır. Eğer kıyaslanan iki öğe de sıra ise bunlar da kendi aralarında kıyaslanırlar. İki sıranın bütün öğeleri aynı bulunursa bu sıralar eşit kabul edilir. Eğer bir sıra diğerinin başından bir kısmı ile aynı ise kısa olan sıra küçük kabul edilir. Karakterlerin kıyaslanmasında ASCII karakter sırası kullanılır. Aynı türden sıraların kıyaslanmasına bazı örnekler : (1, 2, 3) < (1, 2, 4) [1, 2, 3] < [1, 2, 4] 'ABC' < 'C' < 'Pascal' < 'Python' (1, 2, 3, 4) < (1, 2, 4) (1, 2) < (1, 2, -1) (1, 2, 3) == (1.0, 2.0, 3.0) (1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4) Farklı türden nesnelerin kıyaslanmasının yasal olduğuna dikkat edin. Türler alfabetik sırayla dizilmiştir (ingilizce isimlerine göre). Yani: liste < dizge < demet (list < string < tuple). [87] -------------------------------------------------------------------------------- [87] Değişik türlerin kıyaslanmasına ilişkin kurallara güvenilmemeli; gelecek Python sürümlerinde bu kurallar değişebilir! Modüller Python yorumlayıcısını kapatıp tekrar açarsanız yaptığınız tanımlar (işlevler ve değişkenler) kaybolur. Uzunca bir program yazmak isterseniz bunun için programınızı bir metin düzenleyici ile hazırlayıp yazdığınız dosyayı yorumlayıcı girişi olarak kullanırsanız daha iyi olur. Bu işleme betik yazmak denir. Programınız uzadıkça bunu daha kolay idare etmek için birkaç dosyaya bölmek isteyebilirsiniz. Yazdığınız bir işlev tanımını kopyalamaya ihtiyaç duymaksızın birkaç programda kullanmayı da isteyebilirsiniz. Bu iş için Python'da modül denen dosyalar var. Bunlara yazılan tanımlar diğer modüllere ya da etkileşimli kipteki yorumlayıcıya import deyimi ile yüklenebilirler. Modüller .py uzantılı metin dosyalarıdır ve içlerinde Python deyimleri ve tanımları bulur. Bir modül içerisinde __name__ global değişkeninin değeri (bir dizge) o modülün adını verir. Örneğin, favori metin düzenleyiciniz ile fibo.py adlı bir dosya yaratıp Python yorumlayıcısının bulabileceği bir dizine kaydedin. Dosyanın içeriği de şu olsun: # Fibonacci sayıları modülü def fib(n): # n e kadar Fibonacci serisini yazdır a, b = 0, 1 while b < n: print b, a, b = b, a+b def fib2(n): # n e kadar Fibonacci serisi geri döndürür sonuc = [] a, b = 0, 1 while b < n: sonuc.append(b) a, b = b, a+b return sonuc Yorumlayıcıyı açıp bu modülü şu komut ile yükleyin: >>> import fibo Bu fibo içindeki işlev tanımlarını yürürlükte olan simge tablosuna eklemez; sadece modül adı fibo tabloya eklenir. İşlevlere modül adı kullanarak erişilebilir: >>> fibo.fib(1000) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 >>> fibo.fib2(100) [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] >>> fibo.__name__ 'fibo' Bir işlevi sık sık kullanmak isterseniz bunu yerel bir isme atayabilirsiniz: >>> fib = fibo.fib >>> fib(500) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 Modüller Üzerine Daha Fazla Bilgi İşlev tanımlarının yanısıra modül içinde çalıştırılabilir ifadeler de olabilir. Bu ifadeler modülün ilk kullanıma hazırlanması için kullanılabilirler ve sadece modülün ilk yüklenişinde çalışırlar. [88] Her modülün o modül içindeki bütün işlevler tarafından global simge tablosu olarak kullanılan kendi simge tablosu vardır. Bu özellik sayesinde modülü yazan kişi rahatlıkla modül içnde global değişkenler kullanabilir. Modülü kullanan diğer kişilerin global değişkenleri ile isim çakışması olmaz. Modül içindeki global değişkenlere de modulAdi.degiskenAdi şeklinde ulaşmak ve istenirse bunları değiştirmek mümkündür. Modüller diğer modülleri yükleyebilirler. Bütün import ifadelerinin modülün (ya da betiğin) başına konması gelenektendir; ancak şart değildir. Yüklenen modüller kendilerini yükleyen modülün global simge tablosuna ekleniriler. import deyiminin bir modüldeki isimleri doğrudan yükleyen modülün simge tablosuna ekleyen kullanım şekli var. Örnek: >>> from fibo import fib, fib2 >>> fib(500) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 Bu kullanım şeklinde yüklemenin yapıldığı modül adı yerel simge tablosuna eklenmez (yani örnekteki fibo tanımlı değildir). Bir modülde tanımlanmış bütün isimleri de yüklemek şu şekilde mümkündür: >>> from fibo import * >>> fib(500) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 Bu altçizgi ( _ ) ile başlayanlar dışındaki bütün isimleri yükler. Modül Arama Yolu spam isimli bir modül yüklenmek istendiğinde yorumlayıcı önce çalıştırıldığı dizinde ve sonra PYTHONPATH ortam değişkenince tanımlanan dizinler içinde spam.py isimli bir dosya arar. PYTHONPATH dizin isimlerinden oluşan bir listedir (PATH gibi). Aranan dosya bulunmazsa arama, kuruluma bağlı başka bir yolda da aranabilir. Genelde bu /usr/local/lib/python dizinidir. Aslında modüller sys.path değişkeninde bulunan dizin listesinde aranırlar. Bu değişken değerini betiğin alıştırıldığı dizin, PYTHONPATH ve kuruluma bağlı diğer dizinlerden alır. sys.path değişkeni sayesinde Python programları modül arama yolunu değiştirebilirler. "Derlenmiş" Python Dosyaları Derlenmiş Python dosyaları programların çalışmaya başlaması için gereken süreyi kısaltırlar. Örneğin spam.py adlı dosyanın bulunduğu dizinde spam.pyc adlı bir dosya varsa bu modul, spam modülünün ikilik derlenmiş halidir. spam.py dosyasının son değiştirilme tarihi spam.pyc dosyasının içinde de kayıtlıdır ve bu tarihler aynı değil ise .pyc dosyası dikkate alınmaz. spam.pyc dosyasının oluşması için bir şey yapmanız gerekmez. spam.py her ne zaman başarılı olarak derlenirse programın derlenmiş hali spam.pyc dosyasına kaydedilir. Bunun yapılamaması bir hata değildir; herhangi bir nedenle .pyc dosyası tam olarak yazılamazsa geçersiz sayılır ve dikkate alınmaz. .pyc dosyalarının içeriği platformdan bağımsızdır. Bu sayede bir Python modülü dizini farklı mimarideki makineler tarafından paylaşılabilir. Uzmanlar için birkaç ip ucu: Python yorumlayıcısı -O parametresi ile çalıştırıldığında eniyileştirilmiş (optimized) kod üretilir ve .pyo uzantılı dosyalarda saklanır. Eniyileştircinin (optimizer) şu anda pek bir yararı olmuyor; sadece assert deyimlerini siliyor. -O parametresi kullanıldığında tüm ikilik kod eniyileştirilir, .pyc dosyaları göz ardı edilir ve .py dosyaları eniyileştirilmiş ikilik kod olarak derlenir. Yorumlayıcıya iki tane -O parametresi (-OO) vermek derleyicinin bazı ender durumlarda doğru çalışmayan programlara neden olan eniyileştirmeler yapmasına neden olur. Şu anda sadece __doc__ dizgeleri silinerek daha küçük .pyo dosyaları üretilmektedir. Bazı programların çalışması bunların varlığına bağımlı olabileceğinden bu parametreyi kullanırken dikkatli olun. Bir program .pyc ya da .pyo dosyasından okunduğunda .py dosyasından okunan halinden daha hızlı çalışmaz; sadece yüklenme süresi kısalır. Bir betik komut satırından ismi verilerek çalıştırıldığında bunun ikilik kodu asla bir .pyc ya da .pyo dosyasına yazılmaz. Bu yüzden betiğin başlama süresini kısaltmak için bunun bir kısmı bir modüle aktarılarak ve bu modülü yükleyen küçük bir başlatıcı betik kullanılarak kısaltılabilir. Komut satırından bir .pyc ya da .pyo dosyası da ismi verilerek doğrudan çalıştırılabilir. spam.py dosyası olmadan da spam.pyc (ya da -O kullanıldığında spam.pyo) dosyası kullanılabilir. Bunlar bir Python kodu kütüphanesinin tersine mühendisliği zorlaştıran şekilde dağıtılmasında kullanılabilir. compileall modülü bir dizindeki bütün dosyalar için spam.pyc (ya da -O kullanıldığında spam.pyo) dosyaları yaratabilir. -------------------------------------------------------------------------------- [88] Aslında işlev tanımları da `çalıştırılan' ifadelerdir; işlev adını modülün global simge tablosuna eklerler. Standart Modüller Python zengin bir standart modül kütüphanesine sahiptir. Bazı modüller yorumlayıcı ile bütünleşiktir. Bu modüller dilin parçası olmadıkları halde verimlerini artırmak ya da sistem çağrıları gibi işletim sistemine ait özelliklere erişim için yorumlayıcı içine dahil edilmişlerdir. Bunlara iyi bir örnek her Python yorumlayıcısına dahil edilen sys modülüdür. sys.ps1 ve sys.ps2 değişkenleri de birincil ve ikincil komut satırı olarak kullanılan dizgeleri belirlerler: >>> import sys >>> sys.ps1 '>>> ' >>> sys.ps2 '... ' >>> sys.ps1 = 'C> ' C> print 'Böö !' Böö ! C> Bu iki değişken yorumlayıcı sadece etkileşimli kipte iken tanımlıdırlar. sys.path değişkeni de yorumlayıcının modül arama yolunu belirler. Bu değerini ortam değişkeni PYTHONPATH belirler. PYTHONPATH değişkenine değer atanmadıysa sys.path öntanımlı değerini alır. Bunun değeri listelere uygulana işlemler ile değiştirilebilir: >>> import sys >>> sys.path.append('/ufs/guido/lib/python') dir() İşlevi Yerleşik işlev dir() bir modülün hangi isimleri tanımladığını bulmak içik kullanılır. Bu işlev dizgelerden oluşan bir liste geri döndürür: >>> import fibo, sys >>> dir(fibo) ['__name__', 'fib', 'fib2'] >>> dir(sys) ['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__', '__stdin__', '__stdout__', '_getframe', 'argv', 'builtin_module_names', 'byteorder', 'copyright', 'displayhook', 'exc_info', 'exc_type', 'excepthook', 'exec_prefix', 'executable', 'exit', 'getdefaultencoding', 'getdlopenflags', 'getrecursionlimit', 'getrefcount', 'hexversion', 'maxint', 'maxunicode', 'modules', 'path', 'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'version', 'version_info', 'warnoptions'] Argüman kullanmadan çağırılan dir() işlevi o anda tanımlamış olduğunuz isimleri geri döndürür: >>> a = [1, 2, 3, 4, 5] >>> import fibo, sys >>> fib = fibo.fib >>> dir() ['__name__', 'a', 'fib', 'fibo', 'sys'] Bunun değişken, modül, işlev vs. gibi her tür ismini listelediğine dikkat ediniz. dir() yerleşik işlev ve değişkenlerin isimlerini listelemez. Bunların bir listesini isterseniz, standart modül __builtin__ içinde bulabilirsiniz: >>> import __builtin__ >>> dir(__builtin__) ['ArithmeticError', 'AssertionError', 'AttributeError', 'Deprecat |
|
| | #2 |
| Rektör ![]()
Mesajlar: 6.601
Teşekkür etti: 5.392
Teşekkür edildi: 1.949
Forum Gücü: 33 Forum Puanı:2939 ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
paylaşım için teşekkurler
|
|
![]() |
| Konu Seçenekleri | |
| |