Professional Documents
Culture Documents
24.11.2014
IINDEKILER
Temel Bilgiler
1.1 Python Hakknda . . . . . . . . . . . . . . . . . . . . . . . . .
1.2 Pythonu Nereden Bulabilirim? . . . . . . . . . . . . . . . . .
1.2.1
GNU/Linux . . . . . . . . . . . . . . . . . . . . . . .
1.2.2
Microsoft Windows . . . . . . . . . . . . . . . . . . .
1.3 Python Nasl alstrlr? . . . . . . . . . . . . . . . . . . . . .
1.3.1
GNU/Linuxta Pythonu alstrmak . . . . . . . . . .
1.3.2
Windowsta Pythonu alstrmak . . . . . . . . . . .
1.4 print Komutu . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.5 Pythonda Saylar ve Aritmetik Islemler . . . . . . . . . . . . .
1.6 Degiskenler . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.7 Metin Dzenleyici Kullanlarak Python Program Nasl Yazlr?
1.7.1
GNU/Linux Sistemi . . . . . . . . . . . . . . . . . . .
1.7.2
Windows Sistemi . . . . . . . . . . . . . . . . . . . .
1.8 Trke Karakter Sorunu . . . . . . . . . . . . . . . . . . . . .
1.9 Kullancyla Iletisim: Veri Als-Verisi . . . . . . . . . . . . . .
1.9.1
raw_input() fonksiyonu . . . . . . . . . . . . . . . . .
1.9.2
input() fonksiyonu . . . . . . . . . . . . . . . . . . .
1.10 Gvenlik Asndan input() ve raw_input() . . . . . . . . . . .
1.11 Kas Dizileri . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.12 Dnstrme Islemleri . . . . . . . . . . . . . . . . . . . . . .
Pythonda Kosula Bagl Durumlar
2.1 if . . . . . . . . . . . . . . .
2.2 else . . . . . . . . . . . . . .
2.3 elif . . . . . . . . . . . . . .
2.4 Pythonda Girintileme Sistemi
Pythonda Dngler
3.1 while Dngs . .
3.2 for Dngs . . .
3.3 range() fonksiyonu
3.4 len() fonksiyonu .
3.5 break deyimi . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2
2
2
3
3
4
4
5
7
9
12
13
14
18
19
23
23
25
29
30
32
.
.
.
.
34
34
37
38
40
.
.
.
.
.
43
43
48
49
49
50
i
3.6
3.7
4
ii
continue deyimi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
in isleci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Pythonda Fonksiyonlar
5.1 Fonksiyonlar Tanmlamak . . . . . . . . .
5.2 Fonksiyonlarda Parametre Kullanm . . .
5.3 Isimli Argmanlar . . . . . . . . . . . . .
5.4 Gml Fonksiyonlar (Built-in Functions)
5.5 global Deyimi . . . . . . . . . . . . . . .
5.6 return Deyimi . . . . . . . . . . . . . . . .
5.7 pass Deyimi . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
54
54
55
57
57
58
58
59
59
59
59
61
63
66
.
.
.
.
.
.
.
69
70
73
77
81
82
85
87
Modller
6.1 Modlleri Ie Aktarma (importing Modules) . .
6.1.1
import modl_ad . . . . . . . . . . . .
6.1.2
from modl_ad import * . . . . . . . .
6.1.3
from modl_ad import falanca, filanca
6.1.4
import modl_ad as yeni_isim . . . . .
6.2 os Modl . . . . . . . . . . . . . . . . . . . .
6.2.1
name Niteligi . . . . . . . . . . . . . .
6.2.2 listdir Fonksiyonu . . . . . . . . . . . .
6.2.3 getcwd Fonksiyonu . . . . . . . . . . .
6.2.4 chdir Fonksiyonu . . . . . . . . . . . .
6.2.5 mkdir() ve makedirs() Fonksiyonlar . .
6.2.6 rmdir() ve removedirs() fonksiyonlar .
6.2.7 ossep niteligi . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
89
90
92
92
93
93
94
95
96
97
99
99
100
102
slemleri
Dosya I
7.1 Dosya Olusturmak . . . . . . . .
7.2 Dosyaya Yazmak . . . . . . . . .
7.3 Dosyay Okumak . . . . . . . . .
7.4 Dosya Silmek . . . . . . . . . . .
7.5 Dosyaya Rastgele Satr Eklemek .
7.6 Dosyadan Rastgele Satr Silmek .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
105
105
108
110
112
113
115
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Hata Yakalama
117
8.1 try... except... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
8.2 pass Deyimi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
123
123
125
126
126
126
127
127
128
128
128
129
130
130
131
131
132
132
133
133
134
134
135
135
136
136
137
137
138
140
141
141
142
142
142
142
144
145
10 Dzenli Ifadeler
(Regular Expressions)
10.1 Dzenli Ifadelerin Metotlar . . . .
10.1.1 match() Metodu . . . . . .
10.1.2 search() Metodu . . . . . .
10.1.3 findall() Metodu . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
149
150
150
154
155
iii
10.2 Metakarakterler . . . . . . . . . . . . . . . . . . . . . . . . . .
10.2.1 [ ] (Kseli Parantez) . . . . . . . . . . . . . . . . . . .
10.2.2 . (Nokta) . . . . . . . . . . . . . . . . . . . . . . . .
10.2.3 * (Yldz) . . . . . . . . . . . . . . . . . . . . . . . .
10.2.4 + (Art) . . . . . . . . . . . . . . . . . . . . . . . . .
10.2.5 ? (Soru Isareti) . . . . . . . . . . . . . . . . . . . . .
10.2.6 { } (Kme Parantezi) . . . . . . . . . . . . . . . . . .
10.2.7 ^ (Sapka)
. . . . . . . . . . . . . . . . . . . . . . . .
10.2.8 $ (Dolar) . . . . . . . . . . . . . . . . . . . . . . . .
10.2.9 \ (Ters Bl) . . . . . . . . . . . . . . . . . . . . . . .
10.2.10 | (Dik izgi) . . . . . . . . . . . . . . . . . . . . . . .
10.2.11 ( ) (Parantez) . . . . . . . . . . . . . . . . . . . . . .
10.3 Eslesme Nesnelerinin Metotlar . . . . . . . . . . . . . . . . .
10.3.1 group() metodu . . . . . . . . . . . . . . . . . . . . .
10.3.2 groups() metodu . . . . . . . . . . . . . . . . . . . . .
10.4 zel Diziler . . . . . . . . . . . . . . . . . . . . . . . . . . .
10.4.1 Ondalk Saylarn Yerini Tutan zel Dizi: \d . . . . . .
10.4.2 Alfanmerik Karakterlerin Yerini Tutan zel Dizi: \w .
10.5 Dzenli Ifadelerin Derlenmesi . . . . . . . . . . . . . . . . . .
10.5.1 compile() metodu . . . . . . . . . . . . . . . . . . . .
10.5.2 compile() ile Derleme Seenekleri . . . . . . . . . . .
re.IGNORECASE veya re.I . . . . . . . . . . . . . . .
re.DOTALL veya re.S . . . . . . . . . . . . . . . . . .
re.UNICODE veya re.U . . . . . . . . . . . . . . . . .
10.6 Dzenli Ifadelerle Metin/Karakter Dizisi Degistirme Islemleri .
10.6.1 sub() metodu . . . . . . . . . . . . . . . . . . . . . .
10.6.2 subn() metodu . . . . . . . . . . . . . . . . . . . . . .
10.7 Sonu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
157
159
161
162
164
165
167
167
170
171
171
172
174
174
175
176
177
177
179
179
180
180
181
181
182
182
186
186
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
187
187
188
188
189
190
191
192
195
197
203
211
213
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
214
214
214
220
224
iv
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
12.4.1
12.4.2
12.4.3
12.4.4
12.4.5
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
225
227
230
231
232
13 Biim Dzenleyiciler
13.1 Biim Dzenlemede Kullanlan Karakterler . . . . . . . . . . .
13.1.1 d Harfi . . . . . . . . . . . . . . . . . . . . . . . .
13.1.2 i Harfi . . . . . . . . . . . . . . . . . . . . . . . . .
13.1.3 o Harfi . . . . . . . . . . . . . . . . . . . . . . . .
13.1.4 x Harfi . . . . . . . . . . . . . . . . . . . . . . . .
13.1.5 X Harfi . . . . . . . . . . . . . . . . . . . . . . . .
13.1.6 f Harfi . . . . . . . . . . . . . . . . . . . . . . . . .
13.1.7 c Harfi . . . . . . . . . . . . . . . . . . . . . . . . .
13.2 Ileri Dzeyde Karakter Dizisi Biimlendirme . . . . . . . . . .
13.3 Karakter Dizisi Biimlendirmede Szlkleri Kullanmak . . . .
13.4 Saylarda Hassas Biimlendirme . . . . . . . . . . . . . . . . .
13.5 Saylarn Soluna Sfr Eklemek . . . . . . . . . . . . . . . . .
13.6 Karakter Dizilerini Hizalamak . . . . . . . . . . . . . . . . . .
13.7 Karakter Dizilerini Hem Hizalamak Hem de Sola Sfr Eklemek
13.8 format() Metodu ile Biimlendirme . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
233
234
235
235
236
236
236
236
237
238
239
240
241
242
243
244
.
.
.
.
.
.
.
.
.
.
.
.
247
247
248
248
249
249
249
249
250
250
250
251
251
14 math Modl
14.1 sl Ifadeler (pow) . .
14.2 PI says (pi) . . . . .
14.3 Karekk (sqrt) . . . .
14.4 Euler Sabiti (e) . . . .
14.5 exp() Fonksiyonu . . .
14.6 Logaritma (log) . . . .
14.7 log10() Fonksiyonu .
14.8 degrees() Fonksiyonu
14.9 radians() Fonksiyonu .
14.10 Kosins (cos) . . . . .
14.11 Sins (sin) . . . . . .
14.12 Tanjant (tan) . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
253
258
265
271
272
277
279
280
282
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
18.4
18.5
18.6
18.7
18.8
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
283
284
284
285
286
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
290
290
291
295
298
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
301
301
307
308
316
320
324
Degistirmek . . . . . . . . . . . . . . 327
21.2 Pencere Aralarna Simge Eklemek . . . . . . . . . . . . . . . . . . . . . . . 330
21.3 Pencere Aralarna Ipucu Metni (Tooltip) Eklemek . . . . . . . . . . . . . . . 333
22 Nasl Yaplr?
22.1 Tkinterde Fare ve Klavye Hareketleri (Events and Bindings) .
22.1.1 Listbox gelerine Grev Atamak . . . . . . . . .
22.1.2 Pencereleri Baslksz Hale Getirmek . . . . . . . . .
22.1.3 Pencere/Ekran Koordinatlar ve Boyutlar . . . . . .
winfo_height() . . . . . . . . . . . . . . . . . . . . .
winfo_width() . . . . . . . . . . . . . . . . . . . . .
winfo_rootx() . . . . . . . . . . . . . . . . . . . . . .
winfo_rooty() . . . . . . . . . . . . . . . . . . . . . .
winfo_screenheight() . . . . . . . . . . . . . . . . . .
winfo_screenwidth() . . . . . . . . . . . . . . . . . .
22.1.4 Program Tam Ekran olarak alstrmak . . . . . . .
22.1.5 Ekran Ortalamak . . . . . . . . . . . . . . . . . . .
22.1.6 Pencereleri Her Zaman En stte Tutmak . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
336
336
346
348
350
352
353
353
354
355
355
356
356
357
vi
Not: Buradaki belgeler Pythonn 2.7 serisine dair Trke bir klavuz niteligindedir. Eger
Pythonn 3.x srmleri ile alsmak isterseniz belgeler.istihza.com/py3 adresindeki belgeleri
inceleyebilirsiniz.
Not: Eger buradaki belgeleri kagt zerine basl olarak da temin etmek veya istihza.com
projesine destek olmak isterseniz KODLAB Yaynlarndan kan Her Ynyle Python adl
kitabmz satn alabilirsiniz.
Not: istihza.comdaki makalelerin lisans ve kullanm kosullar iin hakknda sayfasna
baknz.
Not: Sorularnz iin istihza.com/forum adresini kullanabilirsiniz.
IINDEKILER
BLM 1
Temel Bilgiler
1.2.1 GNU/Linux
Python hemen hemen btn GNU/Linux dagtmlarnda kurulu olarak geliyor. Mesela
Ubuntuda Pythonun kurulu oldugunu biliyoruz, o yzden Ubuntu kullanyorsanz Pythonu
kurmanza gerek yok.
Ama eger herhangi bir sekilde Pythonu kurmanz gerekirse;
1. ncelikle su adresi ziyaret edin: http://www.python.org/download
2. Bu adreste, Python 2.7.x compressed source tarball (for Linux, Unix or Mac OS X)
baslkl baglantya tklayarak ilgili .tgz dosyasn bilgisayarnza indirin.
3. Daha sonra bu skstrlms dosyay an ve alan dosyann iine girip, orada srasyla
asagdaki komutlar verin:
./configure
make
sudo make altinstall
Bylelikle Pythonun farkl bir srmn sistemimize kurmus olduk. Yalnz burada make
install yerine make altinstall komutunu kullandgmza dikkat edin. make altinstall komutu,
Python kurulurken klasr ve dosyalara srm numarasnn da eklenmesini saglar. Bylece
yeni kurdugunuz Python, sistemdeki eski Python srmn silip zerine yazmams olur ve iki
farkl srm yan yana varolabilir.
Bu noktada bir uyar yapmadan gemeyelim: Python zellikle baz GNU/Linux
dagtmlarnda pek ok sistem aracyla sk skya baglantldr. Yani Python, kullandgnz
dagtmn belkemigi durumunda olabilir. Bu yzden Pythonu kaynaktan kurmak baz riskler
tasyabilir. Eger yukarda anlatldg sekilde, sisteminize kaynaktan Python kuracaksanz,
kars karsya oldugunuz risklerin farknda olmalsnz. Ayrca GNU/Linux zerine kaynaktan
program kurmak konusunda tecrbeli degilseniz, kaynaktan kuracagnz programlarn
bagmllklarnn neler oldugunu, bunlar nasl kuracagnz, program kurduktan sonra nasl
alstracagnz bilmiyorsanz ve eger yukardaki aklamalar size kafa karstrc geliyorsa,
kesinlikle dagtmnzla birlikte gelen Python srmn kullanmalsnz. Python srmlerini
basa bas takip ettigi iin, ben size Ubuntu GNU/Linuxu denemenizi nerebilirim.
Ubuntunun depolarnda Pythonun en yeni srmlerini rahatlkla bulabilirsiniz. Ubuntunun
resmi sitesine http://www.ubuntu.com/ adresinden, yerel Trkiye sitesine ise
http://www.ubuntu-tr.net/ adresinden ulasabilirsiniz.
Gelelim Windows kullanclarnn Pythonu nereden bulacagna...
Eger GNU/Linux isletim sistemi zerinde KDE kullanyorsak Python programn alstrmak
iin ALT+F2 tuslarna basp, kan ekranda su komutu vererek bir konsol ekran ayoruz:
konsole
Eger kullandgmz masast GNOME ise ALT+F2 tuslarna bastktan sonra vermemiz
gereken komut sudur:
gnome-terminal
UNITY masast ortamnda ise CTRL+ALT+T tuslarna basarak dogrudan komut satrna
ulasabiliriz.
Bu sekilde komut satrna ulastktan sonra;
python
yazp ENTER tusuna basarak Python programlama dilini baslatyoruz. Karsmza suna benzer
bir ekran gelmeli:
Python 2.7.4 (default, Apr 10 2013, 12:11:55)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-54)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
Eger python komutunu verdiginizde yukardaki ekran yerine bir hata mesajyla
karslasyorsanz iki ihtimal var:
Birincisi, python kelimesini yanls yazms olabilirsiniz. Mesela yanlslkla pyhton,
pyton, phyton veya Python yazms olabilirsiniz. Dogru kelimenin tamamen kk
harflerden olustuguna zellikle dikkat etmemiz gerekiyor.
Ikincisi, eger ilk maddede sylenenlerin geerli olmadgndan eminseniz, ok dsk bir
ihtimal olmakla birlikte Python sisteminizde kurulu degil demektir. Yalnz GNU/Linux
sistemlerinde Pythonun kurulu olmama ihtimalinin imknsza yakn oldugunu syleyeyim. O
yzden sisteminizde Pythonun kurulu olmadgna kesinkes karar vermeden nce,
durumunuzun birinci madde kapsamna girmediginden emin olmalsnz.
4
Eger yukarda yaptgmz gibi uzun uzun konum belirtmek yerine sadece python komutunu
kullanmak isterseniz Pythonu YOLa (PATH) eklemeniz gerekir. Peki, YOL (PATH) ne
demek?
Bir programn adn komut satrna yazp ENTER dgmesine bastgnzda isletim sisteminiz
aradgnz programn alstrlabilir dosyasn bulabilmek iin dizinler arasnda bir arama
islemi gereklestirir. Elbette isletim sisteminiz ilgili program bulabilmek iin btn isletim
sistemini bastan sona taramaz. Eger byle yapsayd arama islemi ok uzun srerdi. Bunun
yerine, program bulabilmek iin belli basl dizinlerin iini kontrol eder. Eger aranan program
bu dizinler iinde bulabilirse programnz alstrr, bulamazsa da alstramaz.
Peki, isletim sistemimiz, alstrmak istedigimiz program bulmak iin hangi dizinlerin iine
bakar? Bu dizinlerin hangileri oldugunu grmek iin komut satrnda su komutu verin:
echo %PATH%
Iste bu komutun ktsnda grnen ve birbirlerinden ; isareti ile ayrlms dizinler, YOL
(PATH) dizinleridir.
rnegin Windowsta Python programlama dilini kurduktan hemen sonra komut satrnda
python komutunu verirseniz Windows size syle bir hata mesaj verecektir:
C:\Documents and Settings\fozgul>python
'python' i ya da d
s komut, al
strlabilir
program ya da toplu i
s dosyas olarak tannmyor.
nk Windowsa Pythonu ilk kurdugunuzda Python YOLa ekli degildir. Yani Pythonu
kurdugumuz C:\Python27 adl dizin YOL dizinleri arasnda bulunmaz. O yzden Python
programlama dilini yalnzca python komutu ile alstrabilmek iin ncelikle Python
programlama dilinin kurulu oldugu dizini YOL dizinleri arasna eklememiz gerekir.
Peki Pythonu nasl YOLa ekleyecegiz? Syle:
1. Denetim Masas iinde Sistem simgesine ift tklayn. (Eger klasik grnmde
degilseniz Sistem simgesini bulmak iin Performans ve Bakm kategorisinin iine
bakn veya Denetim Masas akken adres ubuguna dogrudan sistem yazp ENTER
tusuna basn.)
2. Gelismis sekmesine girin ve Ortam Degiskenleri dgmesine basn.
3. Sistem Degiskenleri blmnde Path gesini bulup buna ift tklayn.
4. Degisken Degeri ifadesinin hemen karssnda, dizin adlarn ieren bir kutucuk
greceksiniz. Dikkat ederseniz bu kutucuk iindeki geler birbirlerinden ; isareti ile
ayrlms. Biz de ayn yntemi takip ederek, Pythonun kurulu oldugu dizini kutucugun
en sonuna su sekilde ekleyecegiz:
;C:\Python27
5. Simdi
yazp ENTER tusuna bastgnzda karsnza syle bir ekran geliyor olmal:
Python 2.7.4 (default, Apr 6 2013, 19:54:46)
[MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license"
for more information.
>>>
Bu ekranda kullandgmz Python srmnn 2.7.4 oldugunu gryoruz. Buradaki >>> isareti
Pythonun bizden komut almaya hazr oldugunu gsteriyor. Komutlarmz bu isaretten hemen
sonra, bosluk brakmadan yazacagz. Bunun dsnda, istersek Python kodlarn bir metin
dosyasna da kaydedebilir, bu kaydettigimiz metin dosyasn komut satrndan alstrabiliriz.
Bu islemin nasl yaplacagn daha sonra konusacagz.
Eger python komutunu verdiginizde yukardaki ekran yerine bir hata mesajyla
karslasyorsanz ihtimal var:
1. python kelimesini yanls yazms olabilirsiniz. Mesela yanlslkla pyhton, pyton
veya phyton yazms olabilirsiniz. Bu yzden python kelimesini dogru yazdgnza
emin olun.
2. Pythonu YOLa ekleyememis olabilirsiniz.
yukarda
anlattgmz yntemlerden herhangi birini kullanarak Pythonun etkilesimli kabugunu aalm
ve suna benzer bir ekranla karslasalm:
Python 2.7.4 (default, Apr 10 2013, 12:11:55)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-54)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>
yazp hemen ENTER tusuna basalm. (Bu arada yukardaki komutta grdgmz >>>
isaretini kendimiz yazmayacagz. Bize dsen sadece print yazmak.)
Ne oldu? Python bir satr bosluk brakarak alt satra geti, degil mi? Bunu ona yapmasn biz
syledik, o da yapt. . . Simdi
Bu satr yazp ENTER tusuna bastktan sonra ekranda Ben Python, Monty Python! ktsn
grmemiz gerekiyor.
print komutu, Pythondaki en nemli ve en temel komutlardan biridir. Pythonla yazdgnz
programlarda kullanclarnza herhangi bir mesaj gstermek istediginizde bu print
komutundan yararlanacaksnz.
Grdgnz gibi print komutunun ardndan gelen Ben Python, Monty Python! ifadesini ift
trnak iinde belirtiyoruz.
1.4. print Komutu
Python programlama dilinde trnak iinde gsterilen bu tr degerlere karakter dizisi (string)
ad verilir. Karakter dizilerinin ayrt edici zelligi, trnak isaretleri iinde tanmlanms
olmalardr. Eger burada trnak isaretlerini koymazsak veya koymay unutursak Python bize
bir hata kts gsterecektir. Zaten yukardaki komutu verdikten sonra bir hata alyorsanz,
ok byk bir ihtimalle trnaklar dzgn yerlestirmemissinizdir.
Burada biz istersek ift trnak yerine tek trnak () da kullanabiliriz:
>>> print 'Ben Python, Monty Python!'
Karakter dizilerini tanmlarken hangi trnak esidini kullandgmzn nemi yok. nemli olan,
karakter dizisini hangi trnak esidiyle tanmlamaya baslamssak, o trnak esidiyle
kapatmamzdr.
Ancak karakter dizilerini tanmlarken, karakter dizisi iindeki baska kesme ve trnak
isaretlerine kars dikkatli olmalyz.
rnegin:
>>> print "Linux'un faydalar"
Bu komut bize hatasz bir sekilde Linuxun faydalar ktsn verir. Ancak ayn islemi tek
trnakla yapmaya alsrsak syle bir hata mesaj alrz:
File "<stdin>", line 1
print 'Linux'un faydalar'
^
SyntaxError: invalid syntax
Buradaki hatann sebebi de, karakter dizisini baslatp bitiren trnaklarla, Ahmetin szn
aktarmamz saglayan trnak isaretlerinin birbirine karsmasdr.
Bu hatay da su sekilde nleyebiliriz:
>>> print "Ahmet, \"Adana'ya gidiyorum,\" dedi."
Buradaki \ isaretleri olas bir hatadan kamamz saglar. Bu tr ifadelere Python dilinde
Kas Dizileri (Escape Sequences) ad verilir. Kas dizilerinden biraz sonra bahsedecegiz.
Simdilik
Pythonda henz drt drtlk bir program yazamasak da en azndan simdilik onu basit bir
hesap makinesi niyetine kullanabiliriz.
rnegin:
>>> 2 + 5
7
... veya:
>>> 5 - 2
3
... ya da:
>>> 2 * 5
10
... hatta:
>>> 6 / 2
3
+ i
sareti
karma iin
- i
sareti
arpma iin
sareti
* i
blme iin
/ i
sareti
>>> 9 % 2
1
Burada grdgmz ** isleci kuvvet hesaplama islemleri iin kullanlr. Mesela yukardaki
iki rnekte srasyla 2 saysnn 2. ve 3. kuvvetlerini hesapladk.
Tahmin edebileceginiz gibi, ** islecini kullanarak bir saynn karesini ve karekkn de
rahatlkla hesaplayabilirsiniz:
>>> 12 ** 2
144
Bir saynn 2. kuvveti o saynn karesidir. Ayn sekilde bir saynn 0.5. kuvveti de o saynn
karekkdr:
>>> 144 ** 0.5
12.0
Yukarda grdgmz % isleci ise blme isleminden kalan sayy gsterir. rnegin 6 saysn
3e bldgmzde, bu say 3e tam blndg iin kalan 0dr. Bir sonraki rnekte
grdgmz 9 says ise 2ye blndgnde kalan 1 oldugu iin 9 % 2 isleminin degeri 1
olacaktr. Bu isleci kullanarak tek ve ift saylar tespit edebilirsiniz. Eger bir say 2ye
blndgnde kalan 0 ise o say ifttir, aksi halde o say tektir:
>>> 10 % 2
0
5 says ise 2ye blndgnde kalan 0 degildir. Dolaysyla 5, bir tek saydr.
Grdgnz gibi saylar yazarken trnak isaretlerini kullanmyoruz. Eger trnak isareti
kullanrsak Python yazdklarmz say olarak degil karakter dizisi olarak alglayacaktr. Bu
durumu birka rnekle grelim:
>>> 25 + 50
75
Bu komut 25 ile 50yi toplamak yerine, ekrana 25 + 50 seklinde bir kt verecektir. Peki,
syle bir komut verirsek ne olur?
10
Byle bir komutla karslasan Python derhal 25 ve 50 karakter dizilerini (bu saylar trnak
iinde oldugu iin Python bunlar say olarak alglamaz) yan yana getirip birlestirecektir. Yani
syle bir sey yapacaktr:
>>> "25" + "50"
2550
Uzun lafn ksas, 25 ifadesi ile Ben Python, Monty Python! ifadesi arasnda Python
asndan hi bir fark yoktur. Bunlarn ikisi de karakter dizisi snfna girer. Ancak trnak
isareti olmayan 25 ile Ben Python, Monty Python! ifadeleri Python dilinde ayr anlamlar
tasr. nk bunlardan biri tamsay (integer) teki ise karakter dizisidir (string).
Simdi
Ama biz biliyoruz ki 5i 2ye blerseniz 2 degil 2,5 kar. . . Ayn komutu bir de syle
deneyelim:
>>> 5.0 / 2
2.5
Grdgnz gibi blme islemini olusturan bilesenlerden birinin yanna .0 koyulursa sorun
zlyor. Bylelikle Python bizim sonucu tamsay yerine kayan noktal (floating point) say
cinsinden grmek istedigimizi anlyor. Bu .0 ifadesini istedigimiz saynn nne koyabiliriz.
Birka rnek grelim:
>>> 5 / 2.0
2.5
>>> 5.0 / 2.0
2.5
Pythonda aritmetik islemler yaplrken alstgmz matematik kurallar geerlidir. Yani mesela
ayn anda blme karma, toplama, arpma islemleri yaplacaksa islem ncelik sras, nce
blme ve arpma sonra toplama ve karma seklinde olacaktr. rnegin:
>>> 2 + 6 / 3 * 5 - 4
11
Not: Burada __ isaretini iki kez art arda klavyedeki alt izgi tusuna basarak yapabilirsiniz.
Artk bir sonraki Python oturumuna kadar btn islemlerinizin sonucu kayan noktal say
cinsinden gsterilecektir.
Buraya kadar Pythonda tane veri tipi (data type) oldugunu grdk. Bunlar:
1. Karakter dizileri (strings)
2. Tamsaylar (integers)
3. Kayan noktal saylar (floating point numbers)
Pythonda bunlarn dsnda baska veri tipleri de bulunur. Ama biz simdilik veri tiplerine ara
verip degiskenler konusuna deginelim biraz.
skenler
1.6 Degi
Kabaca, bir veriyi kendi iinde depolayan birimlere degisken ad veriyorlar. Ama su anda
aslnda bizi degiskenin ne oldugundan ziyade neye yaradg ilgilendiriyor. O yzden hemen
bir rnekle durumu aklamaya alsalm. Mesela;
>>> n = 5
Su
rneklere bir gz atalm:
12
>>> a = 5
>>> b = 3
>>> a * b
15
>>> print "a ile b'yi arparsak", a * b, "elde ederiz"
a ile b'yi arparsak 15 elde ederiz
Degiskenleri kullanmann baska bir yolu da zel isaretler yardmyla bunlar karakter dizileri
iine gmmektir. Su
rnege bir bakalm:
>>> print "%s ile %s arplrsa %s elde edilir" %(a, b, a*b)
Burada, parantez iinde gsterecegimiz her bir ge iin karakter dizisi iine %s isaretini
ekliyoruz. Karakter dizisini yazdktan sonra da % isaretinin ardndan parantez iinde bu
isaretlere karslk gelen degerleri teker teker tanmlyoruz. Buna gre birinci degerimiz a
(yani 5), ikincisi b (yani 3), ncs ise bunlarn arpm (yani 5 * 3)...
Bu yapy daha iyi anlayabilmek iin bir iki rnek daha verelim:
>>> print "%s ve %s iyi bir ikilidir." %("Python", "Django")
>>> print "%s saysnn karesi %s saysdr." %(12, 12**2)
>>> print "Adm %s, soyadm %s" %("Frat", "zgl")
13
yazmaktr.
Yeni bir Gedit belgesi olusturmak iin ise ALT+F2 tuslarna basp:
gedit
komutunu veriyoruz.
Aslnda metin iine kod yazmak, Python komut satrna kod yazmaktan ok farkl degildir.
Simdi
dosyamz
deneme.py adyla herhangi bir yere kaydediyoruz. Gelin biz masastne kaydedelim
dosyamz. Su
anda masastnde deneme.py adnda bir dosya gryor olmamz lazm.
Simdi
hemen bir konsol ekran ayoruz. (Ama Python komut satrn alstrmyoruz.) Su
14
Bu arada, kodlar Pythonun etkilesimli kabuguna yazmakla metin dzenleyici iine yazmak
arasndaki nemli bir fark, print komutuyla ilgilidir. Etkilesimli kabukta print komutunu
kullansak da kullanmasak da (seklen farkllklar olmakla birlikte) degerler ekrana baslacaktr.
Ama metin dzenleyicide basna print koymadgmz ifadeler ekrana kt olarak verilmez. Bu
durumu daha iyi anlayabilmek iin kendi kendinize denemeler yapmanz tavsiye ederim.
Grdgnz gibi, python deneme.py komutuyla programlarmz alstrabiliyoruz. Peki, ama
acaba Python programlarn basa python komutu eklemeden alstrmann bir yolu var m?
Elbette var. Ancak bunun iin ncelikle baz islemler yapmamz gerekiyor.
Basa python komutu getirmeden programmz alstrabilmek iin ncelikle programmzn
ilk satrna su kodu ekliyoruz:
#!/usr/bin/env python
Bu komutla deneme.py adl dosyay alstrlabilir (executable) bir dosya haline getirmis
oluyoruz.
Artk komut satrnda su komutu vererek programmz alstrabiliriz:
./deneme.py
15
Simdi
tekrar deneyelim:
./deneme.py
16
#!/usr/bin/env python
bu konuyu daha iyi anlayabilmek iin birka deneme yapalm. Hemen bir konsol ekran
ap su komutu veriyoruz:
echo $PATH
sletim
Bu kt bize YOL degiskeni (Ingilizcede PATH variable) dedigimiz seyi gsteriyor. I
sistemimiz, bir program agrmak istedigimizde ncelikle yukarda ad verilen dizinlerin iini
kontrol edecektir. Eger agrdgmz programn alstrlabilir dosyas bu dizinlerden herhangi
birinin iinde ise o program ismiyle agrabiliyoruz.
Simdi
Simdi
konsol ekrannda:
deneme
17
Kodlarmz yazdktan sonra yapmamz gereken sey dosyay bir yere kaydetmek olacaktr.
Bunun iin File/Save as yolunu takip ederek dosyay deneme.py adyla masastne
kaydediyoruz. Dosyay kaydettikten sonra Run/Run Module yolunu takip ederek veya
dogrudan F5 tusuna basarak yazdgmz program alstrabiliriz.
Eger programnz IDLE zerinden degil de, dogrudan MS-DOS komut satrn kullanarak
alstrmak isterseniz su islemleri yapn:
Baslat/alstr yolunu takip edip, alan pencereye cmd yazn ve ENTER tusuna basn.
Su
komutu vererek, masastne, yani dosyay kaydettiginiz yere gelin:
cd Desktop
Windowsta komut satr ilk aldgnda C:\Documents and Settings\kullanici_adi gibi bir
dizinin iinde olacaksnz. Dolaysyla yukarda gsterdigimiz cd Desktop komutu sizi
masastnn oldugu dizine gtrecektir. Tabii eger siz komut satrn farkl bir dizin iinde
amssanz tek basna yukardaki komutu vermeniz sizi masastne gtrmez. yle bir
durumda suna benzer bir komut vermeniz gerekir:
cd C:/Documents and Settings/Kullanici_adi/Desktop
Tabii ben burada sizin Pythonu YOLa eklediginizi varsaydm. Eger Pythonu YOLa
eklemediyseniz programnz alstrmak iin su yntemi de kullanabilirsiniz:
c:/python27/python deneme.py
18
Sizin de tahmin etmis olabileceginiz gibi, ilk kodun alsp, ikinci kodun alsmamasnn
sebebi ikinci kodda yer alan Trke karakterlerdir.
Peki ama neden?
Dikkat ettiyseniz bugn gnlk yasammzda sklkla kullandgmz pek ok sistem bizden
Trke karakterler girmememizi ister. rnegin Gmailden bir e.posta hesab alabilmek iin
belirlememiz gereken parolada Trke karakterler yer alamaz. Bunun sebebi, ok kaba bir
sekilde ifade etmek gerekirse, bilgisayarlarn aslnda yalnzca Ingilizceye zg harfleri
gstermek zere tasarlanms olmasdr. Esasnda btn bilgisayarlarn gvenilir bir sekilde
grntleyebilecegi karakterler http://belgeler.istihza.com/py3/_images/asciifull.png
adresinde greceginiz karakter kmesindekilerden ibarettir. Bu adreste grdgnz karakter
tablosuna ASCII Tablosu (veya ASCII Standard ya da ASCII dil kodlamas) ad verilir.
Biz ilerleyen derslerde ASCII kavramndan ayrntl olarak bahsedecegiz. Simdilik
sadece bu
tablonun btn bilgisayarlarda gvenilir bir sekilde grntlenebilecek harflerin, simgelerin,
isaretlerin tamamn temsil ettigini bilelim yeter.
Iste Python programlama dili de ASCII standard zerine kurulmus bir sistemdir. Bu durumu
ispatlamak iin su kodlar kullanabilirsiniz:
1.8. Trke Karakter Sorunu
19
Dedigimiz gibi, Python ASCII sistemi zerine kuruldugu iin, bu sistemde yer almayan
karakterleri gsteremiyor. Dolaysyla Trke karakterler de bu karakter kmesi iinde yer
almadg iin, bu sistem ile gsterilemiyor.
Not: Siz simdilik ASCII, dil kodlamas, standart, karakter kmesi gibi kavramlara
taklmayn. Ilerde bu kavramlar ayrntl bir sekilde inceleyecegiz. Su
anda sadece bu
sistemin sonular zerine odaklanmamz yeterli olacaktr.
Peki, biz bu durumda Trke karakterleri programlarmzda kullanamayacak myz?
Elbette kullanacagz. Ama bunu yaparken dikkat etmemiz gereken baz kurallar var. Iste bu
blmde bu kurallarn neler oldugunu anlatacagz.
Yazdgmz programlarda Trke karakterleri kullanabilmek iin yapmamz gereken ilk islem,
kodlarmz yazmak iin kullandgmz metin dzenleyicinin dil kodlamas (encoding)
ayarlarn dzgn yapmaktr. Ben size dil kodlamas olarak GNU/Linuxta utf-8i,
Windowsta ise cp1254 (Windows-1254) semenizi tavsiye ederim. Dedigimiz gibi,
Pythonun ntanml dil kodlamas olan ASCII Trke karakterleri gsteremez, ama utf-8 ve
cp1254 Trke karakterleri dzgn bir sekilde grntleyebilme kabiliyetine sahip iki dil
kodlamasdr.
Metin dzenleyicimiz iin uygun bir dil kodlamas seip gerekli ayarlamalar yapyoruz.
20
Elbette etrafta yzlerce metin dzenleyici oldugu iin bu ayarlarn her metin dzenleyicide
nasl yaplacagn tek tek gstermemiz mmkn degil. Ancak iyi bir metin dzenleyicide bu
ayar bulunur. Tek yapmanz gereken, bu ayarn, kullandgnz metin dzenleyicide nereden
yapldgn bulmak. Eger kullandgnz metin dzenleyiciyi ayarlamakta zorlanyorsanz,
http://www.istihza.com/forum adresinde skntnz dile getirebilirsiniz.
Dil kodlamasn ayarladktan sonra, kodlarmzn ilk satrna su ifadelerden birini yazyoruz:
GNU/Linux iin:
# -*- coding: utf-8 -*-
Windows iin:
# -*- coding: cp1254 -*-
Not: Aslnda her iki isletim sisteminde de # -*- coding: utf-8 -*- satr
araclgyla utf-8 adl dil kodlamasn kullanabilirsiniz. Ancak cp1254 adl dil kodlamas,
Windowsta Trke iin biraz daha uygun grnyor. Baz durumlarda, zellikle MS-DOS
komut satrnn utf-8 ile kodlanms programlardaki Trke karakterleri dzgn
gsteremedigine tank olabilirsiniz.
Ardndan Trke karakter ieren program kodlarmz ekleyebiliriz. rnegin:
GNU/Linuxta:
#!/usr/bin/env python
# -*- coding: utf-8 -*print "Merhaba zalim dnya!"
Windowsta:
# -*- coding: cp1254 -*print "Merhaba zalim dnya!"
Grdgnz gibi bu kodlar arasndaki tek fark, kullanlan dil kodlamas: GNU/Linux iin
utf-8, Windows iin ise cp1254 adl dil kodlamasn kullandk. (Tabii bir de Windowsta
herhangi bir islevi olmayan #!/usr/bin/env python satrn Windowstaki kodlardan kardk.)
Bu arada, zaten eger IDLE zerinde alsyorsanz programnz herhangi bir dil kodlamas
belirtmeden kaydetmeye alstgnzda syle bir uyar penceresiyle karslasabilirsiniz:
Burada IDLE, dil kodlamasn belirtmeniz konusunda sizi uyaryor. Eger bu ekranda Edit My
File dgmesine basacak olursanz, IDLE programnzn ilk satrna sizin yerinize # -*coding: cp1254 -*- komutunu ekleyecektir...
Bu kodlar bu sekilde yazp, GNU/Linux dagtmlarnda alstrdgmzda, Trke karakter
ieren programlarmz dzgn bir sekilde alsr. Ancak Windows iin yapmamz gereken bir
islem daha var.
21
5. Tamama basyoruz.
6. Eger karsmza zellikleri Uygula baslkl bir pencere karsa, burada zellikleri,
ayn baslkla ileride olusturulacak pencereler iin kaydet seenegini isaretliyoruz.
Not: Eger yaz tipi ayarlama isleminin nasl yaplacagn grntl olarak da grenmek
isterseniz http://media.istihza.com/videos/ms-dos.swf adresindeki videomuzu izleyebilirsiniz.
Bu islemleri yaparken takip etmemiz gereken temel prensip su: Programmzda hangi dil
kodlamasn kullanyorsak, metin dzenleyici ve komut ekrannda da ayn dil kodlamasn
ayarlamamz gerekir. Mesela yukardaki rnekte, programmz iin cp1254 adl dil
kodlamasn setik. Ayn sekilde, kullandgmz metin dzenleyicinin dil kodlamas
ayarlarnda da cp1254 tercih ettik. Btn bunlara uygun olarak, MS-DOS komut satrnn
dil kodlamasn da 1254 olarak ayarladk. Ayrca MS-DOS iin, Trke karakterleri
gsterebilen bir yaz tipi belirlemeyi de unutmadk.
Esasnda bu konuyla ilgili olarak sylenecek ok sey var. nk aslnda bu konu burada
anlattgmzdan biraz daha karmasktr. Ancak bu asamada kafa karsklgna yol amamak
iin bu konuyu burada kesip yeni bir konuya geiyoruz. Gerekli ayrntlardan ilerleyen
derslerimizde sz edecegiz.
Veri Als-Veri
si
Simdi
Veri Als-Veri
si
23
#!/usr/bin/env python
# -*- coding: utf-8 -*raw_input("Ltfen parolanz girin:")
print "Te
sekkrler!"
Not: Ben bu kitaptaki kodlarda dil kodlamas olarak utf-8i tercih edecegim. Eger
kullandgnz isletim sistemi baska bir dil kodlamas kullanmanz gerektiriyorsa, utf-8 yerine
o dil kodlamasn yazmalsnz (rnegin cp1254).
Simdi
bu belgeyi deneme.py ismiyle kaydediyoruz. Daha sonra bir konsol ekran ap,
programmzn kaytl oldugu dizine geerek su komutla programmz alstryoruz:
python deneme.py
Elbette siz isterseniz daha nce anlattgmz sekilde dosyaya alstrma yetkisi vererek ve
gerekli dzenlemeleri yaparak programnz dogrudan ismiyle de agrabilirsiniz. Bu sizin
tercihinize kalms.
Isterseniz simdi yazdgmz bu program biraz gelistirelim. Mesela programmz su islemleri
yapsn:
Program ilk alstrldgnda kullancya parola sorsun,
Kullanc parolasn girdikten sonra programmz kullancya tesekkr etsin,
Bir sonraki satrda kullanc tarafndan girilen bu parola ekrana yazdrlsn,
Kullanc daha sonraki satrda, parolann yanls oldugu konusunda uyarlsn.
Simdi
Simdi
sekkr ediyoruz:
print "Te
sekkrler!"
Biraz nce raw_input() fonksiyonunu neden bir degiskene atadgmz anladnz sanrm. Bu
sayede dogrudan parola degiskenini agrarak kullancnn yazdg sifreyi ekrana
dkebiliyoruz.
Simdi
Bylelikle, parola degiskenini, yani kullancnn yazdg parolay cmlemizin iine (ya da
Pythonca ifade etmek gerekirse: karakter dizisi iine) eklemis olduk.
Bu parola degiskenini karakter dizisi iine eklemenin baska bir yolu da kodu su sekilde
yazmaktr:
print "Ne yazk ki do
gru parola %s de
gil" %(parola)
Simdi
Veri Als-Veri
si
25
Iste raw_input() ile input() arasndaki fark, yukardaki iki rnek arasndaki farka benzer.
Yukardaki rneklerde, Pythonun saylara ve karakter dizilerine nasl davrandgn gryoruz.
Eger Python iki adet sayyla karslasrsa, bu saylar birbiriyle topluyor. Iki adet karakter
dizisiyle karslasrsa, bu karakter dizilerini birlestiriyor. Bir say, bir de karakter dizisi ile
karslasrsa (saylarla karakter dizileri arasnda herhangi bir birlestirme islemi veya aritmetik
islem yaplamayacag iin) hata veriyor:
>>> "34" + 34
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects
Bu kodlar alstrdgnzda sayy girip ENTER tusuna bastktan sonra syle bir hata mesaj
alacaksnz:
26
Dolaysyla, yukarda hata veren kodlarmzn da dzgn alsabilmesi iin o kodlar syle
yazmamz gerek:
#!/usr/bin/env python
# -*- coding: utf-8 -*soru = "Bir say girin, o saynn karesini syleyeyim:"
sayi = input(soru)
print "girdi
giniz say: %s" %(sayi)
print "girdi
giniz saynn karesi: %s" % (sayi ** 2)
Veri Als-Veri
si
27
islem yapmamza msaade eder. Bu durumu daha iyi anlayabilmek iin mesela asagda
raw_input() fonksiyonuyla yazdgmz kodlar siz bir de input() fonksiyonuyla yazmay
deneyin:
#!/usr/bin/env python
# -*- coding: utf-8 -*isim = raw_input("isminiz: ")
soyisim = raw_input("soyisminiz: ")
print isim, soyisim
Eger bu kodlar input() fonksiyonuyla yazmay denediyseniz, Pythonun ilk veri girisinden
sonra syle bir hata verdigini grmssnzdr:
SyntaxError: invalid syntax
Dolaysyla Pythonun input() fonksiyonuyla bu hatay vermemesi iin de tek yol, kullancnn
ismini ve soyismini trnak iinde yazmas olacaktr. Ama tabii ki normal sartlarda kimseden
ismini ve soyismini trnak iinde yazmasn bekleyemezsiniz.
Btn bunlardan sunu anlyoruz:
input() fonksiyonu, kullancnn geerli bir Python komutu girmesini bekler. Yani eger
kullancnn girdigi sey Pythonun etkilesimli kabugunda hata verecek bir ifade ise, input()lu
kodunuz da hata verecektir.
Dolaysyla eger biz programmz araclgyla kullanclardan baz saylar isteyeceksek ve eger
biz bu saylar isleme sokacaksak (karma, toplama, blme gibi...) input() fonksiyonunu
tercih edebiliriz. Ama eger biz kullanclardan say degil de karakter dizisi girmesini
istiyorsak raw_input() fonksiyonunu kullanacagz.
Simdi
28
Bylece elimizde gayet sk bir derece dnstrme program olmus oldu. Gnn birinde
santigrat dereceleri fayhrenhayta dnstrmeniz gerekirse yukardaki program
kullanabilirsiniz...
bu soruya
cevap olarak sunlar yazalm:
2 + 2
Bunu yazp ENTER tusuna bastgmzda 4 ktsn elde ediyoruz. Bu demek oluyor ki,
input() fonksiyonu kullancdan gelen bilgiyi bir komut olarak yorumladg iin, bu fonksiyon
yardmyla kullanclarmz Python kodlarn alstrabiliyor. Ne gzel, degil mi? Hi de degil!
Basta ok hos bir zellik gibi grnse de bu, aslnda beraberinde baz gvenlik risklerini de
getirir. Simdi
ENTER tusuna bastgnzda, o anda iinde bulundugunuz dizin altndaki dosyalarn ekranda
listelendigini greceksiniz.
Yukardaki satrda geen komutlar henz grenmedik. Ama yukardaki satr yardmyla
sistem komutlarn alstrabildigimizi gryorsunuz. Burada grdgmz dir bir sistem
komutudur. Bu komutun grevi bir dizin altndaki dosyalar listelemek. Mesela GNU/Linuxta
dosya silmemizi saglayan komut rm, Windowsta ise deldir. Dolaysyla yukardaki
komutu su sekilde yazdgmzda neler olabilecegini bir dsnn:
eval("__import__('os').system('rm bir_dosya')")
veya:
1.10. Gvenlik Asndan input() ve raw_input()
29
Hatta bu satr, simdi burada gstermek istemedigimiz, ok daha ykc sonular dogurabilecek
sistem komutlarnn alstrlabilmesini saglar (btn sabit diski silmek gibi...). Dolaysyla
eger zellikle sunucu zerinden alsacak kodlar yazyorsanz input() fonksiyonunu
kullanrken dikkatli olmalsnz.
input() fonksiyonunun yukardaki risklerinden tr Python programclar genellikle bu
fonksiyonu kullanmamay tercih eder. Bunun yerine her zaman raw_input() fonksiyonu
kullanlr. Zaten raw_input() fonksiyonu kullancyla veri als-verisine iliskin btn
ihtiyalarmz karslayacak zelliktedir. Ancak biz henz raw_input() fonksiyonunu tam
kapasite kullanacak kadar bilgi sahibi degiliz. Birka blm sonra eksik bilgilerimizi de
tamamladktan sonra input() fonksiyonuna hi ihtiyacnz olmadgn greceksiniz.
Burada kullandgmz \ isaretine dikkat edin. Bu isaretin yukardaki grevi, tanmlamaya tek
trnakla basladgmz karakter dizisi iinde yine bir tek trnak isareti kullanabilmemizi
saglamaktr. Bu rnegi verdigimizde, bu \ isaretine teknik olarak kas dizisi ad verildigini
sylemistik. Peki, kas dizisi tam olarak ne anlama gelir?
Kas dizileri, kendilerinden hemen sonra gelen karakterlerle birleserek, bu karakterin farkl
veya zel bir anlam kazanmasn saglayan birtakm isaretlerdir. rnegin, Python programlama
dilinde tek trnak ve ift trnak isaretleri karakter dizilerini tanmlamak iin kullanlr. Eger siz
yazdgnz bir kodda tek veya ift trnak isaretlerini farkl bir amala kullanacaksanz kas
dizilerinden yararlanmanz gerekir. Birka rnek verelim:
>>> print '
Istanbul'un 5 gnlk hava tahmini'
Eger bu rnegi bu sekilde yazp alstrrsanz Python size bir hata mesaj gsterecektir.
nk biz burada tek trnak isaretini Istanbul kelimesini un ekinden ayrmak amacyla,
kesme isareti anlamnda kullandk. Python ise bu trnak isaretini karakter dizisi tanmn
bitiren isaret zannetti. Eger yukardaki kodun alsmasn istiyorsak \ adl kas dizisinden
yararlanmalyz:
>>> print '
Istanbul\'un 5 gnlk hava tahmini'
Ayn sekilde ift trnak isareti de Python programlama dilinde karakter dizilerini tanmlamak
iin kullanlr. Eger biz bu isareti baska bir amala kullanacaksak Pythona bu istegimizi
bildirmeliyiz. Bu bildirme isini kas dizileri yardmyla yapabiliriz:
>>> print "Ahmet, "Yarn ben Adana'ya gidiyorum," dedi."
Eger bu kodlar bu sekilde yazp alstrrsak Pythonun bize bir hata mesaj gsterecegini
biliyorsunuz. nk Pythonun, bu kodlar iindeki ift trnak isaretlerinin hangisinin karakter
dizisini baslatp bitiren trnaklar oldugunu, hangisinin ise Ahmetin szlerini aktarmamza
30
yarayan trnak isaretleri oldugunu ayrt etmesi mmkn degil. Bu konuda bizim Pythona
yardmc olmamz gerekiyor. Dikkatlice bakn:
>>> print "Ahmet, \"Yarn ben Adana'ya gidiyorum,\" dedi."
Grdgnz gibi, farkl bir amala kullandgmz her bir trnak isaretini, kas dizileri
yardmyla Pythonun gznden kardk.
Yukardaki rneklerden grdgnz gibi, \ isareti, tek ve ift trnak isaretleri ile birleserek,
bu isaretleri karakter dizileri iinde farkl anlamlarda kullanmamz saglyor. \ adl kas
dizisi baska karakterlerle de birlesebilir. rnegin bu kas dizisini n harfiyle
birlestirdigimizde, yeni satr adl bir kas dizisini elde ederiz. Dikkatlice bakn:
>>> print "Birinci satr\n
Ikinci satr\nnc satr"
Ikinci satr
nc satr
Grdgnz gibi, Python \n isaretleri ile karslastg her noktada yeni bir satra geti. Iste
bunu saglayan sey, \ isaretinin n karakteri ile birleserek olusturdugu yeni satr adl kas
dizisidir. Bildiginiz gibi, n karakterinin grevi aslnda ekrana n harfini basmaktr. Ama bu
karakter \ isareti ile birlestiginde zel bir anlam kazanarak yeni satr adn verdigimiz kas
dizisini olusturuyor.
\n adl kas dizisi Pythonda en fazla kullanacagnz kas dizilerinden biri, belki de
birincisidir. O yzden bu kas dizisini iyi grenmelisiniz.
\ kas dizisinin, birlestiginde zel bir anlam kazanmasn sagladg bir baska karakter de t
karakteridir. Bildiginiz gibi, t karakterinin grevi normalde ekrana t harfini basmaktr.
Ama eger biz bu karakteri \ isareti ile birlestirirsek ortaya sekme adl bir kas dizisi kar.
Hemen bir rnek verelim:
>>> print "uzak...\tok uzak"
uzak... ok uzak
Grdgnz gibi, \t adl kas dizisi sanki TAB (sekme) tusuna basmsz gibi bir etki ortaya
kard. Eger bu etkiyi gremediyseniz birka tane \t kas dizisini art arda kullanabilirsiniz:
>>> print "uzak...\t\tok uzak"
uzak... ok uzak
Pythondaki kas dizileri yukardakilerden ibaret degildir, ama bunlar arasnda en nemlileri
yukarda verdiklerimizdir. Dolaysyla zellikle ilk asamada burada verdigimiz kas dizilerini
grenmeniz islerinizin byk blmn halletmenizi saglayacaktr. Ayrca ilerleyen derslerde,
sras geldike teki kas dizilerinden de sz edecegimizi belirtelim.
31
Islemleri
1.12 Dnstrme
dilerseniz bu duruma
ok basit bir rnek verelim.
Hatrlarsanz, input() ve raw_input() fonksiyonlarn incelerken, input() fonksiyonuyla
yapabilecegimiz her seyi aslnda raw_input() fonksiyonuyla da yapabilecegimizi sylemistik.
Iste int() adl bir fonksiyon bize bu konuda yardmc olacak. Dilerseniz nce bu fonksiyonu
etkilesimli kabukta biraz inceleyelim:
>>> a = "23"
Bylece 23 karakter dizisini sayya evirmis olduk. Ancak tahmin edebileceginiz gibi her
karakter dizisi sayya evrilemez. int() fonksiyonu yalnzca say degerli karakter dizilerini
sayya dnstrebilir:
>>> kardiz = "elma"
>>> int(kardiz)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'elma'
Grdgnz gibi, elma karakter dizisi say olarak temsil edilemeyecegi iin Python bize bir
hata mesaj gsteriyor. Ama 23 gibi bir karakter dizisini say olmaktan karan tek sey
trnak isaretleri oldugu iin, bu karakter dizisi say olarak temsil edilebiliyor... Gelin isterseniz
bu bilgiyi su rnege uygulayalm:
#!/usr/bin/env python
# -*- coding: utf-8 -*ilk_sayi = int(raw_input("
Ilk sayy girin: "))
ikinci_sayi = int(raw_input("
Ikinci sayy girin: "))
toplam = ilk_sayi + ikinci_sayi
print "Bu iki saynn toplam: ", toplam
Grdgnz gibi, burada yaptgmz sey ok basit. raw_input() fonksiyonunu tmden int()
fonksiyonu iine aldk:
32
int(raw_input("
Ilk sayy girin: "))
Burada zellikle kapans trnaklarn eksik yazmamaya zen gsteriyoruz. Pythona yeni
baslayanlarn en sk yaptg hatalardan biri de alms trnaklar kapatmay unutmaktr.
Bylece input() fonksiyonunun prangasndan kurtulmus olduk. Artk raw_input()
fonksiyonuyla da aritmetik islemler yapabiliyoruz. Gelin isterseniz bir rnek daha vererek ne
ile kars karsya oldugumuzu daha iyi anlamaya alsalm:
#!/usr/bin/env python
# -*- coding: utf-8 -*sayi = int(raw_input("Bir say girin. Ben size bu saynn "
"istedi
giniz kuvvetini hesaplayaym: "))
kuvvet = int(raw_input("
Simdi de %s saysnn kanc kuvvetini "
"hesaplamak istedi
ginizi syleyin: " %sayi))
print "%s saysnn %s. kuvveti %s olur." %(sayi, kuvvet, sayi ** kuvvet)
Burada, yazdgmz kodlarn nasl isledigine dikkat etmenin yansra, kodlar grns
asndan nasl dzenledigimize ve satrlar nasl bldgmze de dikkat edin. Daha nce de
dedigim gibi, Python grnse de nem veren zarif bir dildir.
Peki, yukarda yaptgmz seyin tersi mmkn m? Yani acaba bir sayy karakter dizisine
evirebilir miyiz? Bu sorunun yant evettir. Bu islem iin de str() adl fonksiyondan
yararlanacagz:
>>> a = 23
>>> str(a)
'23'
33
BLM 2
Durumlar
Pythonda Kosula
Bagl
2.1 if
If sz Ingilizcede eger anlamna geliyor. Dolaysyla, adndan da anlaslabilecegi gibi,
bu deyim yardmyla Pythonda kosula bagl bir durumu belirtebiliyoruz. Cmle yapsn
anlayabilmek iin bir rnek verelim:
>>> if a == b:
Bu arada, kod iindeki == (ift esittir) isaretini birbirine bitisik olarak yazmamz gerekir.
Yani bu ift esittir isaretini ayr yazmamaya zen gstermeliyiz. Aksi halde yazdgmz
program hata verecektir.
34
Grdgnz gibi cmlemiz su anda yarm. Yani belli ki bunun bir de devam olmas
gerekiyor. Mesela cmlemizi syle tamamlayabiliriz:
>>> if a == b:
...
print "a ile b birbirine e
sittir"
Sizin daha mantkl aklamalar yazacagnz mit ederek konumuza geri dnyoruz...
2.1. if
35
Simdi
yukarda verdigimiz yarm program tamamlamaya alsalm. Hemen bos bir metin
belgesi ap iine sunlar yazyoruz:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
Yukarda a ve b adnda iki tane degisken tanmladk. Bu iki degiskenin de degeri 23.
Programmz yazmaya devam edelim:
#!/usr/bin/env python
# -*- coding: utf-8 -*a = 23
b = 23
if a == b:
print "a ile b birbirine e
sittir."
Grdgnz gibi, burada ncelikle parola adl bir degisken olusturduk. (Bu arada
degiskenlere ad verirken Trke karakter kullanmamalsnz.) Bu parola adl degiskenin
degeri, kullancnn girmesi gereken parolann kendisi oluyor. Ardndan cevap adl baska bir
degisken daha tanmlayp raw_input() fonksiyonunu bu degiskene atadk. Daha sonra da if
deyimi yardmyla, Eger cevap degiskeninin degeri parola degiskeninin degeriyle ayn ise
ekrana Parola onayland! Programa hos geldiniz! yazdr, dedik. Bu program
alstrdgmzda, eger kullancnn girdigi kelime python ise parola onaylanacaktr. Yok,
eger kullanc baska bir kelime yazarsa, program derhal kapanacaktr. Ayn program su
sekilde ksaltarak da yazabiliriz:
36
Durumlar
Blm 2. Pythonda Kosula
Bagl
#!/usr/bin/env python
# -*- coding: utf-8 -*parola = raw_input("Ltfen parolanz giriniz: ")
if parola == "python":
print "Parola onayland! Programa ho
s geldiniz!"
2.2 else
else deyimi ksaca, if deyimiyle tanmlanan kosullu durumlar dsnda kalan btn durumlar
gstermek iin kullanlr. Kk bir rnek verelim:
#!/usr/bin/env python
# -*- coding: utf-8 -*isim = raw_input("Senin ismin ne?")
if isim == "Ferhat":
print "Ne gzel bir isim bu!"
else:
print isim, "adn pek sevmem!"
Burada yaptgmz sey su: ncelikle kullancya, Senin ismin ne? diye soruyoruz. Bu
soruyu, isim ad verdigimiz bir degiskene atadk. Daha sonra su cmleyi Pythoncaya
evirdik:
Eger isim degiskeninin degeri Ferhat ise, ekrana Ne gzel bir isim bu! cmlesini yazdr.
Yok, eger isim degiskeninin degeri Ferhat degil de baska herhangi bir seyse, ekrana isim
degiskeninin degerini ve adn pek sevmem! cmlesini yazdr.
Bu grendigimiz else deyimi sayesinde artk kullanc yanls parola girdiginde uyar mesaj
gsterebilecegiz:
#!/usr/bin/env python
# -*- coding: utf-8 -*parola = raw_input("Ltfen parolanz giriniz: ")
if parola == "python":
print "Parola onayland! Programa ho
sgeldiniz!"
else:
print "Ne yazk ki, yanl
s parola girdiniz!"
2.2. else
37
2.3 elif
Eger bir durumun gereklesmesi birden fazla kosula baglysa elif deyiminden faydalanyoruz.
Mesela:
#!/usr/bin/env python
# -*- coding: utf-8 -*meyve = raw_input("Bir meyve ad yaznz: ")
if meyve == "elma":
print "elma bir meyvedir"
elif meyve == "armut":
print "armut bir meyvedir"
else:
print meyve, "bir meyve de
gildir!"
Bu program alstrldgnda btn olas sonular listelenecektir. Yani ktmz syle olacaktr:
sayi
sayi
sayi
sayi
100'dr
150'den kktr
50'den byktr
100'den kktr veya 100'e e
sittir
38
Durumlar
Blm 2. Pythonda Kosula
Bagl
#!/usr/bin/env python
# -*- coding: utf-8 -*sayi = 100
if sayi == 100:
print "sayi 100'dr"
elif sayi <= 150:
print "sayi 150'den kktr"
elif sayi > 50:
print "sayi 50'den byktr"
elif sayi <= 100:
print "sayi 100'den kktr veya 100'e e
sittir"
Grdgnz gibi programmz elif deyimini kullanarak yazarsak Python belirtilen kosulu
karslayan ilk sonucu ekrana yazdracak ve orada duracaktr.
Buraya kadar Pythonda pek ok sey grenmis olduk. if, elif, else deyimlerini de
grendigimize gre artk ok basit bir hesap makinesi yazabiliriz:
#!/usr/bin/env python
# -*- coding: utf-8 -*from __future__ import division
secenek1
secenek2
secenek3
secenek4
print
print
print
print
=
=
=
=
"(1)
"(2)
"(3)
"(4)
toplama"
karma"
arpma"
blme"
secenek1
secenek2
secenek3
secenek4
soru = raw_input("Yaplacak i
slemin numarasn girin: ")
if soru ==
sayi1
print
sayi2
print
if soru ==
sayi3
print
sayi4
print
if soru ==
2.3. elif
"1":
= input("Toplama iin ilk sayy girin: ")
sayi1
= input("Toplama iin ikinci sayy girin: ")
sayi1, "+", sayi2, ":", sayi1 + sayi2
"2":
= input("karma iin ilk sayy girin: ")
sayi3
= input("karma iin ikinci sayy girin: ")
sayi3, "-", sayi4, ":", sayi3 - sayi4
"3":
39
sayi5
print
sayi6
print
if soru ==
sayi7
print
sayi8
print
Bu rnek program inceleyip, programn nasl alstgn anlamaya ugrasr, eksik yanlarn
tespit eder ve bu eksikleri giderme yollar zerinde kafa yorarsanz (mesela bu program
input() yerine raw_input() ile nasl yazabileceginizi dsnrseniz), verdigimiz bu basit rnek
amacna ulasms demektir.
Bu kodlar daha sonra okuyacak kisilerin nefretini kazanmak dsnda, kodlar bu sekilde
yazmamz herhangi bir soruna neden olmaz. Yani yukarda gsterilen her iki kod da
derleyiciler (compiler) tarafndan ayn sekilde okunup, basaryla derlenecektir. Eger
yazdgnz kodlarn okunakl olmasn istiyorsanz, yukarda gsterilen ilk kodlama biimini
tercih etmeniz gerekir. Ama dedigim gibi, ikinci kodlama biimini kullanmanz da
programnzn alsmasn etkilemez.
Ancak Pythonla ilgilenen herkesin ok iyi bildigi gibi, Python programlama dilinde
girintileme basit bir slup meselesi degildir.
Yani yukardaki C kodlarnn yaptg isi Pythonla yerine getirmek istersek syle bir kod
yazmamz gerekir:
40
Durumlar
Blm 2. Pythonda Kosula
Bagl
a = 1
if a == 1:
print "Elveda Zalim Dnya"
Bu kodlarn sahip oldugu girintileme yaps Python asndan byk nem tasr. rnegin
yukardaki kodlar su sekilde yazamayz:
a = 1
if a == 1:
print "Elveda Zalim Dnya"
te yandan, bu isin bir de sizin pek elinizde olmayan bir boyutu vardr. Eger yazdgnz kodlar
birden fazla kisi tarafndan dzenleniyorsa, sekme ayarlar dzgn yaplmams bir metin
dzenleyici kullanan kisiler kodunuzun girinti yapsn allak bullak edebilir. Bu yzden, ortak
2.4. Pythonda Girintileme Sistemi
41
proje gelistiren kisilerin de sekme ayarlar konusunda belli bir kural benimsemesi ve bu
konuda da tutarl olmas gerekir. Ingilizce bilenler iin, bu girintileme konusuyla ilgili
http://wiki.python.org/moin/HowToEditPythonCode adresinde gzel bir makale
bulunmaktadr. Bu makaleyi okumanz tavsiye ederim.
42
Durumlar
Blm 2. Pythonda Kosula
Bagl
BLM 3
Pythonda Dngler
Hatrlarsanz bir nceki blmn sonlarna dogru basit bir hesap makinesi yapmstk. Ancak
dikkat ettiyseniz, o hesap makinesi programnda toplama, karma, arpma veya blme
islemlerinden birini seip, daha sonra o setigimiz islemi bitirdigimizde program kapanyor,
baska bir islem yapmak istedigimizde ise program yeniden baslatmamz gerekiyordu. Ayn
sekilde kullanc ad ve parola soran bir program yazsak, su anki bilgilerimizle her defasnda
program yeniden baslatmak zorunda kalrz. Yani kullanc ad ve parola yanls girildiginde
bu kullanc ad ve parolay tekrar tekrar soramayz; program yeniden baslatmamz gerekir.
Iste bu blmde Pythonda yazdgmz kodlar srekli hale getirmeyi, tekrar tekrar
dndrmeyi grenecegiz.
Kodlarmz srekli dndrmemizi saglamada bize yardmc olacak paracklara Pythonda
dng (Ingilizce: Loop) ad veriliyor. Bu blmde iki tane dngden bahsedecegiz: while ve
for dngleri. Ayrca bu blmde dngler dsnda break ve continue deyimleri ile range() ve
len() fonksiyonlarna da deginecegiz. Bylece ilerleyen blmlerde isleyecegimiz daha
karmask konular biraz daha kolay anlamamz saglayacak temeli edinecegiz. Isterseniz laf
daha fazla uzatmadan yola koyulalm ve ilk olarak while dngsyle ise baslayalm...
Bu minicik kodun yaptg is, birinci satrda a degiskeninin degerine bakp ikinci satrda bu
degere 1 eklemek, nc satrda da bu yeni degeri ekrana yazdrmaktr. Dolaysyla bu kod
43
parasnn verecegi kt da 1 olacaktr. Bu kty verdikten sonra ise program sona erecektir.
Simdi
Bu kodu alstrdgmzda, 1den 100e kadar olan saylarn ekrana yazdrldgn grrz.
Konuyu anlayabilmek iin simdi de satrlar teker teker inceleyelim:
Ilk satrda, 0 degerine sahip bir a degiskeni tanmladk.
Ikinci ve nc satrlarda, a degiskeninin degeri 100 saysndan kk oldugu mddete a
degiskeninin degerine 1 ekle, cmlesini Pythoncaya evirdik.
Son satrda ise, bu yeni a degerini ekrana yazdrdk.
Iste bu noktada while dngsnn faziletlerini gryoruz. Bu dng sayesinde programmz
son satra her gelisinde basa dnyor. Yani:
1. a degiskeninin degerini kontrol ediyor,
2. ann 0 oldugunu gryor,
3. a degerinin 100den kk oldugunu idrak ediyor,
4. a degerine 1 ekliyor (0 + 1 = 1),
5. Bu degeri ekrana yazdryor (1),
6. Basa dnp tekrar a degiskeninin degerini kontrol ediyor,
7. ann su anda 1 oldugunu gryor,
8. a degerinin hl 100den kk oldugunu anlyor,
9. a degerine 1 ekliyor (1 + 1 = 2),
10. Bu degeri ekrana yazdryor (2),
11. Bu islemi 99 saysna ulasana dek tekrarlyor ve en sonunda bu sayya da 1 ekleyerek
vuslata eriyor.
Burada ilerleyebilmek iin ihtiyacmz olacak baz islem yardmclarna veya baska bir
ifadeyle islelere (operators) deginelim:
Simdiye
44
=
=
=
=
"(1)
"(2)
"(3)
"(4)
toplama"
karma"
arpma"
blme"
secenek1
secenek2
secenek3
secenek4
soru = raw_input("Yapaca
gnz i
slemin numarasn girin: ")
if soru ==
sayi1
print
sayi2
print
if soru ==
sayi3
print
"1":
= input("Toplama iin ilk sayy girin: ")
sayi1
= input("Toplama iin ikinci sayy girin: ")
sayi1, "+", sayi2, ":", sayi1 + sayi2
"2":
= input("karma iin ilk sayy girin: ")
sayi3
45
sayi4
print
if soru ==
sayi5
print
sayi6
print
if soru ==
sayi7
print
sayi8
print
Dedigimiz gibi, program bu haliyle her defasnda yalnzca bir kez islem yapmaya izin
verecektir. Yani mesela toplama islemi bittikten sonra program sona erecektir. Ama eger biz
bu programda su ufack degisikligi yaparsak isler degisir:
#!/usr/bin/env python
# -*- coding: utf-8 -*from __future__ import division
while True:
secenek1
secenek2
secenek3
secenek4
print
print
print
print
=
=
=
=
"(1)
"(2)
"(3)
"(4)
toplama"
karma"
arpma"
blme"
secenek1
secenek2
secenek3
secenek4
soru = raw_input("Yapaca
gnz i
slemin numarasn girin: ")
if soru == "1":
sayi1 = input("Toplama iin ilk sayy girin: ")
print sayi1
sayi2 = input("Toplama iin ikinci sayy girin: ")
print sayi1, "+", sayi2,":", sayi1 + sayi2
if soru == "2":
sayi3 = input("karma iin ilk sayy girin: ")
print sayi3
sayi4 = input("karma iin ikinci sayy girin: ")
print sayi3, "-", sayi4,":", sayi3 - sayi4
if soru == "3":
sayi5 = input("arpma iin ilk sayy girin: ")
print sayi5
sayi6 = input("arpma iin ikinci sayy girin: ")
print sayi5, "x", sayi6,":", sayi5 * sayi6
if soru == "4":
46
sayi7
print
sayi8
print
47
if soru != "Python":
print "Yanl
s cevap!"
Simdilik
Bu kod yardmyla ekrana 1den 100e kadar olan saylar yazdrabiliyorduk. Ayn islemi daha
basit bir sekilde for dngs (ve range() fonksiyonu) yardmyla da yapabiliriz:
#!/usr/bin/env python
# -*- coding: utf-8 -*for i in range(1, 100):
print i
Ben burada degisken ad olarak i harfini kullandm, siz isterseniz baska bir harf veya kelime
de kullanabilirsiniz.
Yukardaki Pythonca kod Trkede asag yukar su anlama gelir:
1- 100 aralgndaki saylarn her birine i adn verdikten sonra ekrana inin degerini yazdr!
for dngsyle ilgili su rnege de bir bakalm:
#!/usr/bin/env python
# -*- coding: utf-8 -*for kelimeler in "linux":
print kelimeler
Bylelikle Pythonda while ve for dnglerini de grenmis olduk. Bu arada dikkat ettiyseniz,
for dngs iin verdigimiz ilk rnekte dng iinde yeni bir fonksiyon kullandk. Isterseniz
bu vesileyle biraz da hem dnglerde hem kosullu ifadelerde hem de baska yerlerde karsmza
kabilecek faydal fonksiyonlara ve ifadelere deginelim:
48
Bu komut ise 1 ile 100 arasndaki saylar 2ser 2ser atlayarak yazdrmamz saglar.
Hemen for dngsyle range() fonksiyonunun birlikte kullanldg bir rnek verip baska bir
fonksiyonu anlatmaya baslayalm:
#!/usr/bin/env python
# -*- coding: utf-8 -*for sarki in range (1, 15):
print sarki, "mumdur"
49
len() fonksiyonunu yalnzca karakter dizileri ile birlikte kullandgmza dikkat edin. Ilerde bu
fonksiyonu baska veri tipleri ile birlikte kullanmay da grenecegiz. Ancak henz o veri
tiplerini grmedik. Dolaysyla simdilik bu fonksiyonun karakter dizileriyle birlikte
kullanlabildigini, ama saylarla birlikte kullanlamadgn bilmemiz yeterli olacaktr. Yani
syle bir rnek bizi hsrana ugratr:
>>> sayi = 123456
>>> len(sayi)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'int' has no len()
Burada grdgmz hata mesaj bize, tamsay veri tipinin len() fonksiyonu ile birlikte
kullanlamayacagn sylyor. Ama syle yaparsak olur:
>>> sayi = 123456
>>> kardiz = str(sayi)
>>> len(kardiz)
6
123456 saysn str() fonksiyonu yardmyla bir karakter dizisine dnstrdgmz iin len()
fonksiyonu grevini yerine getirecektir.
50
else:
print "Kullanc adnz veya parolanz yanl
s."
print "Ltfen tekrar deneyiniz!"
a ve b dogru ise derseniz, burada hem ann hem de bnin dogru olmas gerekir.
51
Eger kullanc tarafndan girilen say haneli veya daha az haneli bir say ise, continue
deyiminin etkisiyle:
print "En fazla haneli bir say girin."
3.7 in isleci
for dngsn anlattgmz ksmda, bu dngnn szdizimi iinde in adl bir isle
dikkatinizi ekmis olmal:
>>> for i in falanca:
... ...
Bu rnekte in isleci yardmyla i adl karakterin istihza adl karakter dizisi iinde olup
olmadgn sorguladk. Bu karakter istihza adl karakter dizisi iinde getigi iin de True
cevabn aldk.
Bir de suna bakalm:
>>> 'e' in kardiz
False
istihza adl karakter dizisi iinde e karakteri olmadg iin bu defa da False kts aldk.
Bu islecin gerek hayatta nasl kullanlabilecegine dair bir rnek verelim:
# -*- coding: utf-8 -*cevap = raw_input("Sistemden kmak istedi
ginize emin misiniz? [E/H] ")
if 'E' in cevap or 'e' in cevap:
print "Gle gle!"
else:
print "Sistemden klmad!"
52
Bu kodlara gre, ncelikle kullancya sistemden kmak isteyip istemedigini soruyoruz. Eger
kullancnn verdigi cevap iinde E veya e karakterleri varsa kullancy sistemden
karyoruz. Aksi halde kullancy sistemden karmyoruz.
Grdgnz gibi, bu kodlarda or ve in adl isleleri kullandk. or isleci kodlarmza ya
da anlam verirken, in isleci iinde anlam verdi. Dolaysyla yukardaki kodlar su sekilde
Trkelestirebiliriz:
E
ger cevap iinde 'E' varsa veya cevap iinde 'e' varsa:
ekrana 'Gle gle!' ifadesini bas.
Aksi halde:
ekrana 'Sistemden klmad!' ifadesini bas.
Btn bu rneklerden de anlayacagnz gibi, in isleci herhangi bir genin herhangi bir veri
tipi iinde olup olmadgn sorgulamamz saglyor. Ilerleyen blmlerde baska veri tiplerini
de grendigimizde bu islecin ne kadar faydal bir ara oldugunu siz de anlayacaksnz.
3.7. in isleci
53
BLM 4
Bu blmde Pythonda drt yeni veri tipi daha grenecegiz. grenecegimiz bu veri tipleri
liste (list), demet (tuple), szlk (dictionary) ve sral szlk (ordereddict). Burada nasl liste,
demet, szlk ve sral szlk olusturulacagn grenmenin yansra, bu veri tipleriyle neler
yapabilecegimizi de grmeye alsacagz.
Ilk konumuz listeler.
4.1 Listeler
Dilerseniz listenin ne demek oldugunu tanmlamaya alsmakla vakit kaybetmek yerine
dogrudan konuya girelim. Bylece soyut kavramlarla kafa karstrmadan ilerlememiz
mmkn olabilir.
Listeleri kullanabilmek iin yapacagmz ilk is, listeyi tanmlamak olacak. Pythonda herhangi
bir liste olusturmak iin nce listemize bir ad vermemiz, ardndan da kseli parantezler iinde
bu listenin gelerini belirlememiz gerekiyor. Yani liste olustururken dikkat etmemiz gereken
iki temel nokta var. Birincisi tpk degiskenlere isim veriyormusuz gibi listelerimize de isim
vermemiz gerekiyor. Tabii listelerimizi isimlendirirken Trke karakterler kullanmayacagz.
Ikincisi, listemizi olusturan geleri kseli parantezler iinde yazacagz.
Simdi
Daha nce de syledigimiz gibi, burada dikkat etmemiz gereken nokta, liste gelerini
tanmlarken kseli parantezler kullanyor olmamz. Ayrca liste iindeki karakter dizilerini her
zamanki gibi trnak iinde belirtmeyi unutmuyoruz. Tabii ki saylar yazarken bu trnak
isaretlerini kullanmayacagz. Eger saylarda trnak isareti kullanrsanz Pythonun bu geleri
nasl alglayacagn biliyorsunuz. Bakalm bunlar Python nasl alglyormus?
Python komut satrnda su ifadeyi yazn:
>>> type("Hale")
Bu komutun kts:
54
olacaktr. Yani Hale ifadesinin tipi str imis. Str, Ingilizcedeki string kelimesinin
ksaltmas. Trke anlam ise karakter dizisi.
Simdi
Demek ki 123 ifadesinin tipi int imis. Bu int de Ingilizcedeki integer kelimesinin
ksaltmas oluyor. Trke anlam tamsaydr.
Simdi
Grdgnz gibi yazdgnz sey say da olsa, siz bunu trnak iinde belirtirseniz, Python bunu
say olarak alglamyor.
Neyse biz konumuza dnelim.
Olmas gerektigi sekilde listemizi tanmladk:
>>> liste = ["Hale", "Jale", "Lale", 12, 23]
Simdi
komut satrnda:
>>> liste
Simdi
listeleri ynetmeyi; yani listeye ge ekleme, listeden ge karma gibi islemleri nasl
yapacagmz grenecegiz. Bu isi Pythonda baz paracklar (ya da daha teknik bir dille
sylemek gerekirse metotlar...) yardmyla yapyoruz.
Isterseniz gelin simdi bu metotlarn neler olduguna ve nasl kullanldklarna bakalm.
4.1.1 append
Ilk metodumuz append(). Bu kelime Trkede eklemek, ilistirmek anlamna geliyor.
Olusturdugumuz listeye yeni bir ge eklemek iin append() metodundan faydalanyoruz:
4.1. Listeler
55
liste.append("Mehmet")
Dikkat edin, liste tanmlarken kseli parantez kullanyorduk. Listeleri ynetirken ise (yani
metotlar kullanarak ekleme, karma, vb. yaparken) normal parantezleri kullanyoruz. Ayrca
grdgnz gibi, bu append() metodunu, liste isminin yanna koydugumuz bir noktadan sonra
yazyoruz. append() metodu yardmyla, olusturdugumuz bir listenin en sonuna ge
ekleyebiliyoruz. Peki, bu metot yardmyla birden fazla ge ekleyebilir miyiz? Ne yazk ki,
append() metodu bize listeye yalnzca tek bir ge ekleme olanag sunar.
Eger biz ekleyecegimiz bir geyi en sona degil de listenin belirli bir noktasna yerlestirmek
istiyorsak, baska bir metottan faydalanyoruz. Ama bu yeni metodu kullanmaya baslamadan
nce Pythonun liste gelerini sralama ynteminden bahsetmemiz gerekir. Pythonun
sralama yntemi ile ilgili olarak bilinmesi gereken en nemli kural sudur: Python, liste (ve
teki veri tipleri) iindeki geleri sralarken, ilk geyi 0dan baslatr.
Yani:
>>> liste = ["Hale", "Jale", "Lale", 12, 23, "Mehmet"]
biiminde grdgmz listenin ilk gesine 0nc ge denir. Bu listedeki birinci ge ise
Jaledir.
Pythonda bir listenin gelerine erismek iin asagdaki yapy kullanyoruz:
>>> liste[0]
Bu komutu yazdgmzda Python bize 0nc genin Hale oldugunu syleyecektir. Ayn
sekilde;
>>> liste[2]
komutu ise bize 2. genin Lale oldugunu syleyecektir. Ancak burada suna dikkat etmemiz
lazm: Python liste gelerini numaralarken 0dan baslasa da liste gelerini sayarken 1den
baslar. Yani;
>>> len(liste)
56
Pythonun ge sralama mantgn grendigimize gre, simdi listenin en sonuna degil de kendi
belirleyecegimiz baska bir noktasna ge eklememizi saglayacak metodu grebiliriz.
4.1.2 insert
Iste bu insert() metodu yardmyla listenin herhangi bir noktasna ge ekleyebiliyoruz. Bu
kelime Trkede yerlestirmek, sokmak anlamna geliyor. insert metodu yardmyla listenin
1. srasna (Dikkat edin, 0nc sraya demiyoruz.) Ahmeti yerlestirebiliriz:
>>> liste.insert(1, "Ahmet")
Burada parantez iindeki ilk say, Ahmet gesinin liste iinde yerlestirilecegi sray
gsteriyor. Listemizin son durumunu kontrol edelim:
>>> liste
Grdgnz gibi, 1 says Python iin ilk anlamna gelmiyor. Eger listemizin en basna
bir ge eklemek istiyorsak su komutu kullanacagz:
>>> liste.insert(0, "Veli")
Bu metot da tpk append() metodunda oldugu gibi listeye yalnzca bir adet ge eklememize
izin verir.
4.1.3 extend
Bu kelime genisletmek, uzatmak anlamna geliyor. extend() metodu, olusturdugumuz
listeleri genisletmemizi veya uzatmamz saglar. Bu metodun islevini anlatabilmenin en
iyi yolu tabii ki rnekler zerinde alsmak. Simdi
Simdi
Grdgnz gibi, extend() metodu iki listenin gelerini tek bir liste iinde birlestirmeye
yaryor. Ya da baska bir ifadeyle, bir listeyi genisletiyor, uzatyor. extend() metoduyla
yaptgmz islemin aynsn + islecini kullanarak su sekilde de yapabiliriz:
>>> liste = liste + yeni_liste
Burada yaptgmz sey, liste ve yeni_liste adl listelerin gelerini bir araya toplayp btn
geleri tekrar liste adl listeye atamaktan ibarettir.
4.1. Listeler
57
4.1.4 remove
Liste olusturmay, append() ve insert() metotlar yardmyla listeye geler eklemeyi grendik.
Peki, ya listemizden ge karmak istersek ne yapacagz? Pythonda bu isi yapmamz
saglayan iki tane metot var. Biz nce bunlardan ilki olan remove() metoduna bakacagz. Bu
kelime Trkede karmak, kaldrmak, silmek anlamna geliyor.
Diyelim ki yukarda tanmladgmz listeden Nouma gesini karmak/kaldrmak istiyoruz.
O zaman su komutu vermemiz gerekir:
>>> liste.remove("Nouma")
Eger listede Nouma adl birden fazla ge varsa, Python listede buldugu ilk Noumay
karacaktr.
4.1.5 pop
Ingilizcede pop kelimesi, frlamak, prtlamak, aniden almak gibi anlamlar tasyor. Biz
bu kelimeyi internette bir adrese tkladgmzda aniden nmze kan pop uplardan yani
alr pencerelerden hatrlyoruz. Pythonda listeler ile birlikte kullandgmz pop() metodu
ise listeden bir ge silerken, bu sildigimiz genin ekrana yazdrlmasn saglyor.
Su
komutu deneyelim:
>>> liste.pop()
Grdgnz gibi, Python bu pop() metodu yardmyla listenin son gesini karacak, stelik
kardg geyi ekrana yazdracaktr. Eger bu komutu syle verirsek ne olur?
>>> liste.pop(0)
Bu komut ise listedeki ilk yani 0nc geyi karr ve kardg geyi ekrana yazdrr.
Anladgnz gibi pop() ile remove() arasndaki en temel fark pop() metodunun silinen geyi
ekrana yazdrmas, remove() metodunun ise yazdrmamasdr. Ayrca pop() metodunda isim
belirterek listeden silme islemi yapamazsnz. Mutlaka silinecek genin liste iindeki srasn
vermelisiniz. remove() metodunda da bu durumun tam tersi sz konusudur. Yani remove()
metodunda da sra belirtemezsiniz; isim vermeniz gerekir...
Simdiye
kadar:
1. bir listenin en sonuna nasl ge ekleyecegimizi (append()),
2. listenin herhangi bir yerine nasl ge ekleyecegimizi (insert()),
3. listeden isim vererek nasl ge karacagmz (remove()),
4. listeden say vererek nasl ge karacagmz (pop())
grendik.
Buraya kadar grendigimiz metotlar listenin boyutunda degisiklikler yapmamz saglyordu.
Simdi
4.1.6 index
Diyelim ki listedeki Jardel gesinin listenin kanc srasnda oldugunu merak ediyorsunuz.
Iste bu index() metodu sizin aradgnz sey! Bunu syle kullanyoruz:
>>> liste.index("Jardel")
Bu komut, Jardel gesinin liste iinde kanc srada oldugunu gsterecektir bize...
4.1.7 sort
Bazen listemizdeki geleri alfabe srasna dizmek isteriz. Iste byle bir durumda
kullanacagmz metodun ad sort():
>>> liste.sort()
4.1.8 reverse
Bu metot listedeki gelerin srasn ters yz eder. Syle
ki:
>>> liste.reverse()
Bu komutu st ste iki kez verirseniz listeniz ilk haline dnecektir. Yani bu komut aslnda
sort() metodunun yaptg gibi alfabe srasn dikkate almaz. Listenizdeki gelerin srasn ters
evirmekle yetinir.
4.1.9 count
Listelerle birlikte kullanabilecegimiz baska bir metot da budur. Grevi ise liste iinde bir
genin ka kez getigini sylemektir:
>>> liste.count("Prekazi")
4.1. Listeler
59
grendik...
Bunlarn yansra Pythonun liste gelerini kendi iinde sralama mantgn da grendik. Buna
gre unutmamamz gereken sey; Pythonun liste gelerini saymaya 0dan basladg. Isterseniz
bu mantk zerine baz alsmalar yapalm. rnegin sunlara bir bakalm:
>>> liste[0]
Bu komut listenin ilk yani 0nc gesini ekrana yazdracaktr. Dikkat edin, yine kseli
parantez kullandk.
Peki, listedeki son geyi agrmak istersek ne yapacagz? Eger listemizde ka tane ge
oldugunu bilmiyorsak ve len() komutuyla bunu grenmeyecek kadar tembelsek su komutu
kullanacagz:
>>> liste[-1]
Tabii ki siz len(liste) komutu verip nce listenin uzunlugunu da grenebilirsiniz. Buna gre,
Python saymaya 0dan basladg iin, kan saynn bir eksigi listenin son gesinin srasn
verecektir. Yani eger len(liste) komutunun kts 5 ise, listedeki son geyi:
>>> liste[4]
komutuyla da agrabilirsiniz...
Olur ya, eger kulagnz tersten gstermek isterseniz len(liste) komutuyla buldugunuz sayy
eksiye dnstrp listenin ilk gesini de agrabilirsiniz. Yani, eger len(liste) komutunun
kts 5 ise:
>>> liste[-5]
komutu size ilk geyi verecektir, tpk liste[0] komutunun yaptg gibi...
Python bize bu mantk zerinden baska olanaklar da tanyor. Mesela tanmladgmz bir
listedeki gelerin tamamn degil de yalnzca 2. ve 3. geleri grmek istersek su komuttan
faydalanyoruz (saymaya 0dan baslyoruz):
>>> liste[2:4]
Grdgnz gibi, yukardaki komutta birinci say dhil, ikinci say hari olacak sekilde bu
ikisi arasndaki geler listelenecektir. Yani liste[2:4] komutu listedeki 2. ve 3. geleri
yazdracaktr.
Eger : isaretinden nce veya sonra herhangi bir say belirlemezseniz Python varsaylan
olarak oraya ilk veya son geyi koyacaktr:
>>> liste[:3]
Ayn sekilde;
60
>>> liste[0:]
Bu listenin en sonuna bir veya birden fazla ge eklemek iin (append() metoduna benzer
sekilde...)
>>> liste[5:5] = ["domates", "salata"]
komutunu kullanyoruz.
Hatrlarsanz, append() metoduyla listeye yalnzca bir adet ge ekleyebiliyorduk. Yukardaki
yntem yardmyla birden fazla ge de ekleyebiliyoruz listeye.
Bu listenin 3. srasna bir veya birden fazla ge yerlestirmek iin su komutu kullanabiliriz
(insert() metoduna benzer sekilde.)
>>> liste[3:3] = ["kebap", "lahmacun"]
Bu listenin 2. srasndaki geyi silip yerine bir veya birden fazla ge eklemek iin:
>>> liste[2:3] = ["nane", "limon"]
Bu listenin 2. srasndaki geyi silip yerine bir veya birden fazla geye sahip bir liste
yerlestirmek iin de syle bir sey yazyoruz:
>>> liste[2] = ["ruj", "maskara", "rimel"]
Hangi islemi yapmak iin nasl bir say dizilimi kullandgmza dikkat edin. Bu komutlar
baslangta biraz karsk gelebilir. Ama eger yeterince rnek yaparsanz bu komutlar
karstrmadan uygulamay grenebilirsiniz.
Artk listeler konusunu burada noktalayp demetler (tuples) konusuna geebiliriz...
4.2 Demetler
Demetler listelere benzer. Ama listeler ile aralarnda ok temel bir fark vardr. Listeler
zerinde oynamalar yapabiliriz. Yani ge ekleyebilir, ge karabiliriz. Demetlerde ise byle
bir sey yoktur.
4.2. Demetler
61
Peki tek geli bir demet nasl olusturulur? O kadar basit degil. Aslnda basit ama biraz tuhaf:
>>> demet = ("su",)
Grdgnz gibi, tek geli bir demet olusturabilmek iin genin yanna bir virgl koyuyoruz!
Hemen teyit edelim:
>>> type(demet)
<type 'tuple'>
Demek ki, virgl koymazsak demet degil, alelade bir karakter dizisi olusturmus oluyoruz.
Yukarda anlattgmz sekilde bir demet olusturma isine demetleme (packing) ad veriliyor.
Bunun tersini de yapabiliriz. Buna da demet zme deniyor (unpacking).
nce demetleyelim:
>>> aile = "Anne", "Baba", "Kardesler"
Simdi
demeti zelim:
62
>>> a, b, c = aile
Bu sekilde komut satrna a yazarsak, Anne gesi; b yazarsak Baba gesi; c yazarsak
Kardesler gesi ekrana yazdrlacaktr. Demet zme isleminde dikkat etmemiz gereken
nokta, esittir isaretinin sol tarafnda demetteki ge says kadar degisken ad belirlememiz
gerektigidir.
Peki, listeler varken bu demetler ne ise yarar? diye sordugunuzu duyar gibiyim.
Bir defa, demetler listelerin aksine degisiklik yapmaya msait olmadklarndan listelere gre
daha gvenlidirler. Yani yanlslkla degistirmek istemediginiz veriler ieren bir liste
hazrlamak istiyorsanz demetleri kullanabilirsiniz. Ayrca demetler listelere gre daha hzl
alsr. Dolaysyla bir program iinde sonradan degistirmeniz gerekmeyecek verileri
gruplamak iin liste yerine demet kullanmak daha mantkldr.
4.3 Szlkler
Szlgn ne demek oldugunu tanmlamadan nce gelin isterseniz ise bir rnekle baslayalm:
>>> sozluk = {"elma": "meyve", "domates": "sebze", 1: "sayi"}
Burada mesela, elma bir anahtar, meyve ise bu anahtarn degeridir. Ayn sekilde
sebze degerinin anahtar domatestir. Dolaysyla Pythonda szlk; anahtar ve deger
arasnda bag kuran bir veri tipidir.
Mesela bir adres veya telefon defteri yazmak istedigimizde bu szlklerden faydalanabiliriz.
Yani szlk denince aklmza sadece bildigimiz szlkler gelmemeli. Su
rnege bir
bakalm:
>>> telefon_defteri = {"Ahmet": "0533 123 45 67", ... "Salih": "0532321 54 76",
... "Selin": "0533 333 33 33"}
Burada kodlarmzn saga dogru biimsiz bir biimde uzamamas iin virglden sonra ENTER
tusuna basarak geleri tanmlamaya devam ettigimize dikkat edin. Saga dogru ok fazla
uzams olan kodlar hem grnt asndan hos degildir, hem de grs alann dagttg iin
okumay zorlastrr.
Szlk tanmlarken dikkat etmemiz gereken birka nokta var. Bunlardan birincisi geleri
belirlerken kme parantezlerini kullanyor olmamz. Ikincisi karakter dizilerinin yansra
saylar da trnak iinde gsteriyor olmamz. Isterseniz saylar trnaksz kullanrsanz ne
olacagn deneyerek grebilirsiniz. Ancak eger gireceginiz say ok uzun degil ve 0 ile
baslamyorsa bu sayy trnaksz da yazabilirsiniz. ncs iki nokta st ste ve virgllerin
nerede, nasl kullanldgna da dikkat etmeliyiz. Simdi
veya:
4.3. Szlkler
63
>>> telefon_defteri["Salih"]
Bu komutlar Ahmet ve Salih adl anahtarlarn karssnda hangi deger varsa onu
ekrana yazdracaktr. Dikkat edin, szlkten ge agrrken kme parantezlerini degil, kseli
parantezleri kullanyoruz. Bu arada aklnzda bulunsun, szlk iindeki geleri anahtara
gre agryoruz, degere gre degil. Yani iki nokta st ste isaretinin solundaki ifadeleri
kullanyoruz geleri agrrken, sagndakileri degil...
Simdi
Buradan anladgmz su: Bir szlge yeni bir ge eklerken de, varolan bir geyi degistirirken
de ayn komutu kullanyoruz. Demek ki bir geyi degistirirken aslnda geyi degistirmiyor,
silip yerine yenisini koyuyoruz.
Eger bir geyi listeden silmek istersek su komutu kullanyoruz:
del telefon_defteri["Salih"]
Su
son rnekte grdgmz clear() ifadesi, Python szlklerinin metotlarndan biridir.
Szlklerin bunun dsnda baska metotlar da vardr. Bunlar iinde en nemlileri ise keys() ve
values() adl metotlardr. Ksaca sylemek gerekirse keys() metodu bir szlkteki anahtarlar,
values() metodu ise szlkteki degerleri verir. Mesela:
>>> print telefon_defteri.keys()
['Ahmet', 'Salih', 'Selin']
>>> print telefon_defteri.values()
['0533 123 45 67', '0532 321 54 76', '0533 333 33 33']
64
if soru == "istanbul":
print "gk grltl ve sa
ganak ya
g
sl"
elif soru == "ankara":
print "ak ve gne
sli"
elif soru == "izmir":
print "bulutlu"
else:
print "Bu
sehre ili
skin havadurumu \
bilgisi bulunmamaktadr."
Ama yukardaki yntemin, biraz mesakkatli olacag ak. Sadece sehir iin hava durumu
bilgilerini sorgulayacak olsak mesele degil, ancak onlarca sehri kapsayacak bir program
retmekse amacmz, yukardaki yntem yerine daha pratik bir yntem uygulamak gayet
yerinde bir tercih olacaktr. Iste bu noktada programcnn imdadna Pythondaki szlk veri
tipi yetisecektir. Yukardaki kodlarn yerine getirdigi islevi, su kodlarla da gereklestirebiliriz:
#!/usr/bin/env python
# -*- coding: utf-8 -*soru = raw_input("
Sehrinizin adn tamam kk \
harf olacak
sekilde yaznz: ")
cevap = {"istanbul":"gk grltl ve sa
ganak ya
g
sl",
"ankara":"ak ve gne
sli", "izmir":"bulutlu"}
print cevap.get(soru,"Bu
sehre ili
skin havadurumu \
bilgisi bulunmamaktadr.")
Grdgnz gibi, ilk nce normal biimde, kullancya sorumuzu soruyoruz. Ardndan da
anahtar-deger iftleri seklinde sehir adlarn ve bunlara karslk gelen hava durumu
bilgilerini bir szlk iinde depoluyoruz. Daha sonra, szlk metotlarndan biri olan get()
metodunu seiyoruz. Bu metot bize szlk iinde bir degerin varolup olmadgn denetleme
imknnn yansra, ad geen degerin szlk iinde varolmamas durumunda kullancya
gsterilecek bir mesaj seme olanag da sunar. Python szlklerinde bulunan bu get() metodu
bizi bir else veya sonraki derslerimizde isleyecegimiz try-except blogu kullanarak hata
yakalamaya ugrasma zahmetinden de kurtarr.
Burada print cevap.get(soru,Bu sehre iliskin hava durumu bilgisi bulunmamaktadr.) satr
yardmyla soru adl degiskenin degerinin szlk iinde varolup varolmadgn
sorguluyoruz. Eger kullancnn girdigi sehir ad szlgmz iinde bir anahtar olarak
tanmlanmssa, bu anahtarn degeri ekrana yazdrlacaktr. Eger kullancnn girdigi sehir ad
szlgmz iinde bulunmuyorsa, bu defa kullancya Bu sehre iliskin hava durumu bilgisi
bulunmamaktadr. biiminde bir mesaj gsterilecektir.
if deyimleri yerine szlklerden yararlanmann, yukarda bahsedilen faydalarnn dsnda bir
de su yararlar vardr:
1. ncelikle sz geen senaryo iin szlkleri kullanmak programcya daha az kodla
daha ok is yapma olanag saglar.
2. Szlk programcnn elle olusturacag if-elif-else bloklarndan daha performansldr
4.3. Szlkler
65
Liste ve demetlerde geleri sralarna gre agrabiliyoruz. nk liste ve demetler sral veri
tipleridir. Yani liste ve demetlerdeki gelerin her birinin bir sras vardr. Ancak szlkler yle
degildir. Szlklerde herhangi bir sra kavram bulunmaz. Mesela su rnege bakalm:
>>> a = {"a": 1, "b": 2, "c": 3}
>>> print a
{'a': 1, 'c': 3, 'b': 2}
66
Burada, alsanlar ise giris tarihlerine gre sraladk. Ancak bu szlg ekrana
yazdrdgmzda bu sra bozulacaktr:
>>> print personel
{'Selin': '30.06.2013', 'Ahmet': '19.01.2013', 'Mehmet': '21.03.2013'}
Grdgnz gibi, ise en son giren kisi Selindi. Ama ktda bu kisi en basta grnyor.
Dedigimiz gibi, bu durumun sebebi szlklerin srasz bir veri tipi olmasdr.
Iste eger herhangi bir sekilde szlk yaps iinde tanmladgnz gelere, bu geleri
tanmladgnz sra ile erismeniz gerekirse Pythondaki baska bir aratan yararlanacaksnz.
Bu zel aracn ad OrderedDict.
OrderedDict, collections adl bir modl iinde yer alr. Biz henz modl konusunu
islemedik. Ama Python programlama dilinde simdiye kadar grendiklerimiz sayesinde biraz
sonra anlatacaklarmz rahatlkla anlayabilecek kadar Python bilgisine sahibiz. O halde
hemen rnegimizi verelim. . .
Hatrlarsanz, saylar konusundan bahsederken, iki tam say arasndaki bir blme isleminin
sonucunun ksuratsz olacagn, yani bu blme isleminin sonucunun da bir tam say olacagn
grenmistik:
>>> 5/2
2
Normal sartlar altnda 5 saysn 2ye bldgmzde 2.5 saysn elde ederiz. Ama blme
islemine giren 5 ve 2 saylar birer tam say oldugu iin, blme isleminin sonucu da tam say
oluyor. Eger blme isleminde ondalk ksmlar da grmek istersek syle bir kod
yazabiliyorduk:
>>> 5.0 / 2.0
2.5
Grdgnz gibi, burada __future__ adl bir modl iindeki division adl bir arac kullandk.
Ayn sekilde Pythondaki sral szlklerden faydalanabilmek iin de bir modl iindeki baska
bir arac kullanacagz. Dikkatlice bakn:
>>> from collections import OrderedDict
Dedigimiz gibi, OrderedDict, collections adl bir modl iinde yer alr. Iste biz de
yukardaki satr yardmyla bu modln iindeki OrderedDict adl arac kodlarmzn iine
aktardk. Bylece bu arac kodlarmzda kullanabilecegiz.
Sral szlkleri syle tanmlyoruz:
4.4. Sral Szlkler
67
Grdgnz gibi, sral szlkler bir liste iindeki iki geli demetler seklinde tanmlanyor.
Bu demetlerdeki ilk ge szlk anahtarlarn, ikinci ge ise szlk degerlerini temsil ediyor.
Yalnz bu tanmlama sekli gznze biraz ugrastrc grnms olabilir. Eger yleyse, sral
szlkleri su sekilde de tanmlayabilirsiniz:
nce bos bir sral szlk olusturalm:
>>> personel = OrderedDict()
Simdi
BLM 5
Pythonda Fonksiyonlar
Simdi
syle bir dsnn: Diyelim ki alstgnz isyerinde her gn bir yerlere bir dileke
gnderiyorsunuz. Aslnda farkl yerlere gnderdiginiz bu dilekeler temel olarak ayn ierige
sahip. Yani mesela dilekeyi Mehmet Beye gndereceginiz zaman yazya Mehmet Beyin
adn; Ahmet Beye gndereceginiz zaman ise Ahmet Beyin adn yazyorsunuz. Ayrca tabii
dileke zerindeki tarih bilgilerini de gne gre dzenliyorsunuz.
Mantkl bir insan, yukardaki gibi bir durumda elinde bir dileke taslag bulundurur ve sadece
degistirmesi gereken ksmlar degistirip dilekeyi hazr hale getirir. Her defasnda ayn
bilgileri en bastan yazmaz.
Dilerseniz anlattgmz bu durumu Python programlama dili ile temsil etmeye alsalm:
# -*- coding: utf-8 -*print """Sayn Mehmet Bey,
19.12.2009 tariginde yapt
gmz ba
svurunun sonulandrlmas
hususunda yardmlarnz rica ederiz.
Sayglarmzla,
Orun Kunek"""
Bu dileke Mehmet Beye gidiyor. Isterseniz bir tane de Ahmet Beye yazalm...
print """Sayn Ahmet Bey,
15.01.2010 tariginde yapt
gmz ba
svurunun sonulandrlmas
hususunda yardmlarnz rica ederiz.
Sayglarmzla,
Orun Kunek"""
Burada dikkat ederseniz iki dilekenin metin ierigi aslnda ayndr. Sadece bir-iki yer
degisiyor. Bu kodlar bu sekilde yazmak olduka verimsiz bir yoldur. nk bu sistem hem
programcya ok vakit kaybettirir, hem fazlasyla kopyala-yapstr islemi gerektirir, hem de bu
kodlarn bakmn yapmak ok zordur. Eger dileke metni zerinde bir degisiklik yapmak
isterseniz program iindeki ilgili kodlar tek tek bulup dzeltmeniz gerekir. Yani mesela
yukardaki iki dilekenin ayn program iinde oldugunu varsayarsak, dileke metnindeki bir
hatay dzeltmek istedigimizde ayn dzeltmeyi birka farkl yerde yapmamz gerekir.
rnegin yukardaki dileke metninde bir yazm hatas var. Ilk satrda tarihinde
69
yazacagmza tariginde yazmsz... Tabii biz Mehmet Beye yazdgmz dilekenin metnini
Ahmet Beye yazacagmz dilekeyi hazrlarken kopyala-yapstr yaptgmz iin ayn hata
Mehmet Beye gidecek dilekede de var. Simdi
Bylece eksiksiz bir fonksiyon tanmlams olduk. Burada dikkat etmemiz gereken en nemli
sey, def fonksiyon_adi(): satrndan sonra gelen ksmn girintili yazlmasdr.
Simdi
70
71
Dedigimiz gibi, bu fonksiyon, def selamla(): satryla baslar, print naslsn? satryla biter.
Fonksiyon agrs dedigimiz selamla() satr bu fonksiyonun dsndadr. nk bu satr
selamla() fonksiyonunun gvdesini olusturan girintili ksmn dsnda yer alyor.
Eger bu sylediklerimiz size biraz kafa karstrc gelmisse, hi endise etmenize gerek yok.
Tam olarak ne demek istedigimizi biraz sonra gayet net bir sekilde anlamanz saglayacak
rnekler verecegiz.
Dilerseniz bu blm kapatmadan nce fonksiyonlarla ilgili birka basit bir rnek daha
yaparak bu konuya snmanz saglayalm:
# -*- coding: utf-8 -*-
72
Bu kodlarda zellikle fonksiyonlarn nerede baslayp nerede bittigine dikkat edin. Daha nce
de dedigimiz gibi, bir fonksiyon def paracgyla baslar, gvdesindeki girintili alann sonuna
kadar devam eder. Girintili alann dsnda kalan btn kodlar o fonksiyonun dsndadr.
Mesela yukardaki rnekte tek() ve cift() birbirinden bagmsz iki fonksiyondur. Bu
fonksiyonlardan sonra gelen say degiskeni de fonksiyon alannn dsnda yer alr.
Belki fark ettiniz, belki de fark etmediniz, ama burada aslnda ok nemli bir sey yaptk.
Fonksiyonumuza bir parametre verdik! Simdiye
73
selamla("istihza")
Burada selamla() adl fonksiyonu istihza argman ile birlikte agrdk. Bylece ktda
istihza degerini aldk. Burada terminolojiyle ilgili ufak bir not dselim: Fonksiyonlar
tanmlanrken parantez iinde belirtilen degerlere parametre ad verilir. Ayn fonksiyon
agrlrken parantez iinde belirtilen degerlere ise argman ad verilir. Ama her iki durum
iin de parametre adnn kullanldgn da grebilirsiniz baz yerlerde...
Neyse... Biz bu terminoloji isini bir kenara brakp yolumuza devam edelim.
Eger selamla() adl fonksiyonu farkl bir argman ile agrrsak elbette alacagmz kt da
farkl olacaktr:
def selamla(isim):
print "merhaba, benim adm %s!" %isim
selamla("Ahmet Efendi")
Burada nemli olan nokta, selamla() adl fonksiyonun bir adet parametreye sahip olmasdr.
Dolaysyla bu fonksiyonu argmansz olarak veya birden fazla argmanla agramayz. Yani
fonksiyonu su sekillerde agrmak hata almamza yol aacaktr:
selamla("Ahmet", "Mehmet")
veya:
selamla()
sum() fonksiyonu, kendisine argman olarak verilen bir say listesinin gelerini birbiriyle
toplayp sonucu bize bildiriyor. Ancak Pythonda bu sum() fonksiyonuna benzer bir sekilde
74
bir say listesini alp, gelerini birbiriyle arpan hazr bir fonksiyon bulunmuyor. Python bize
bu islem iin herhangi bir hazr fonksiyon sunmadgndan, byle bir durumda kendi
yntemimizi kendimiz icat etmek zorundayz. O halde hemen baslayalm. Diyelim ki
elimizde syle bir say listesi var:
>>> sayilar = [45, 90, 43]
Soru su: Acaba bu listedeki saylar birbiriyle nasl arparz? Bunu yapmann en kolay yolu,
listedeki btn saylar 1le arpp, btn degerleri tek bir degisken iinde toplamaktr. Yani
ncelikle degeri 1 olan bir degisken belirlememiz gerekiyor:
>>> a = 1
Daha sonra listedeki btn saylar a degiskeninin degeriyle arpp, bu degeri yine a
degiskenine atayacagz:
>>> for i in sayilar:
...
a = a * i
Bylece listedeki btn saylarn arpmn gsteren deger a degiskenine atanms oldu.
Isterseniz bu a degerini yazdrp sonucu kendi gzlerinizle grebilirsiniz:
>>> print a
174150
174150
Simdi
75
icat eder, sonra gereken yerlerde icat ettigi bu tekerlegi kullanr. Biz de yukardaki islemleri
ieren bir fonksiyonu tek bir kez tanmlayacagz ve program iinde gereken yerlerde bu
fonksiyonu agracagz. Simdi
Bylece taslagmz olusturmus olduk. Artk bu fonksiyonu kullanarak istedigimiz bir say
grubunu birbiriyle rahatlkla arpabiliriz. Bunun iin yapmamz gereken tek sey carp() adl
fonksiyonu agrmak:
carp([3, 5, 7])
Burada dikkat ederseniz, carp() fonksiyonuna verdigimiz saylar bir liste iine aldk. nk
carp() fonksiyonu tek bir parametre alyor. Eger bu fonksiyonu su sekilde agrrsanz hata
alrsnz:
carp(3, 5, 7)
Simdi
Ayrca dileke metninde bir degisiklik yapmak istedigimizde sadece fonksiyon gvdesini
dzenlememiz yeterli olacaktr.
77
Yine burada, kodlarmzn irkin bir grnt olusturmamas iin geleri nasl alt satra
geirdigimize dikkat edin. Eger Python kodlarna duyarl bir metin dzenleyici
kullanyorsanz (mesela IDLE) virgl isaretlerinden sonra ENTER tusuna bastgnzda dzgn
girinti yaps otomatik olarak olusturulacaktr.
Bu kodlarda ncelikle kayit_ekle() adl bir fonksiyon tanmladk. Bu fonksiyon toplam alt
adet parametre alyor. Bunlar; isim, soyisim, sehir, meslek, tel ve adres.
Tanmladgmz bu fonksiyonun gvdesinde ilk olarak kayit adl bir szlk olusturduk. Bu
szlk, ekleyecegimiz baglantya dair bilgileri tutacak. Daha sonra, olusturdugumuz bu
szlge ge ekliyoruz. Buna gre, fonksiyon parametrelerinden olan isim ve soyisim;
kayit adl szlkteki anahtar ksmn olusturacak. sehir, meslek, tel ve adres
degerleri ise kayit adl szlkteki deger ksmn meydana getirecek.
Szlg olusturduktan sonra ekrana Baglant bilgileri kaytlara eklendi! biiminde bir mesaj
yazdryoruz.
Daha sonra da kayt adl szlgn gelerini belli bir dzen erevesinde ekrana
yazdryoruz.
Bu islemi nasl yaptgmza dikkat edin. Python szlklerinde items() adl bir metot bulunur.
Bu metot yardmyla bir szlk iinde bulunan btn anahtar ve deger iftlerini elde
edebiliriz. Dilerseniz buna bir rnek verelim. Diyelim ki elimizde syle bir szlk var:
>>> sozluk = {"programlama dili": "Python",
... "metin duzenleyici": "Kwrite"}
Simdi
Grdgnz gibi, sozluk adl szlge ait btn anahtar ve degerler bir liste iinde demetler
halinde topland. Simdi
ekmemizi saglyor. Bylece isim ve soyismi, fonksiyondaki teki bilgilerden grsel olarak
ayrms oluyoruz.
En son olarak da kayit adl szlgn deger ksmndaki geleri tek tek ekrana yazdryoruz...
Fonksiyonumuzu basaryla tanmladktan sonra sra geldi bu fonksiyonu agrmaya...
Fonksiyonumuzu srasyla, Orun, Kunek, Adana, Sarkc,
0322 123 45 67 ve
Baraj Yolu argmanlaryla birlikte agryoruz. Bylece bu kodlar alstrdgmzda syle
bir kt elde ediyoruz:
Ba
glant bilgileri kaytlara eklendi!
Orun Kunek
----------Adana
Sarkc
0322 123 45 67
Baraj Yolu
=
=
=
=
=
=
raw_input("isim: ")
raw_input("soyisim: ")
raw_input("
sehir: ")
raw_input("meslek: ")
raw_input("telefon: ")
raw_input("adres: ")
Yukardaki fonksiyonlar kullanrken dikkat etmemiz gereken ok nemli bir nokta var.
kayit_ekle() adl fonksiyonu kullanrken argman olarak verecegimiz degerlerin sras byk
nem tasyor. Yani bu degerleri, fonksiyon tanmndaki sraya gre yazmamz gerek. Buna
gre kayit_ekle() fonksiyonunu agrrken, ilk argmanmzn isim, ikincisinin soyisim,
ncsnn sehir, drdncsnn meslek, besincisinin telefon, altncsnn ise adres olmas
gerekiyor. Aksi halde, bizim yukarda verdigimiz rnekte ok belli olmasa da, fonksiyondan
alacagmz kt hi de bekledigimiz gibi olmayabilir. Ancak takdir edersiniz ki, bu kadar
fazla sayda parametrenin srasn aklda tutmak hi de kolay bir is degil. Iste bu noktada
Pythondaki isimli argmanlar devreye girer ve bizi byk bir dertten kurtarr. Nasl m?
5.3. Isimli Argmanlar
79
"I
s Geli
stirme Mdr",
3500,
25)
Iste bu rnekte, parametre/argman sralamasnn nemi ortaya kar. Eger burada mesela
Ahmet ncel argmanyla 3500 argmannn yerini degistirirseniz programnz hata
verecektir. nk bu fonksiyonda biz 3500 saysn kullanarak aritmetik bir islem yapyoruz.
Eger 3500n olmas gereken yerde bir say yerine karakter dizisi olursa aritmetik islem
yaplamaz... Bu arada yukardaki fonksiyonun saga dogru ok fazla yaylarak irkin bir kod
80
81
Burada her zamanki gibi fonk() adl bir fonksiyon tanmladk ve daha sonra bu fonksiyonu
agrdk. Sonu olarak bu fonksiyonu alstrdgmzda 5 ktsn aldk...
Grdgnz gibi, fonksiyon iinde a adl bir degiskenimiz var. Simdi
Bu hata mesaj bize a diye bir degisken olmadgn sylyor. Halbuki biz fonk() adl
fonksiyon iinde bu a degiskenini tanmlamstk, degil mi? O halde neden Python a
degiskenini bulamadgndan yaknyor? Hatrlarsanz bu blmn en basnda, bir fonksiyonun
82
snrlarnn ne oldugundan sz etmistik. Buna gre yukardaki fonk() adl fonksiyon def
fonk(): ifadesiyle baslyor, print a ifadesiyle bitiyor. Bu fonksiyonun etkisi bu alanla snrldr.
Pythonda buna isim alan (namespace) ad verilir. Herhangi bir fonksiyon iinde tanmlanan
her sey o fonksiyonun isim alanyla snrldr. Yani mesela yukardaki fonksiyon iinde
tanmladgmz a degiskeni yalnzca bu fonksiyon snrlar dhilinde geerlidir. Bu alann
dsna kldgnda a degiskeninin herhangi bir geerliligi yoktur. O yzden Python
yukardaki gibi bir kod yazdgmzda a degiskenini bulamayacaktr. Isterseniz bu durumu
daha iyi anlayabilmek iin yukardaki rnegi syle degistirelim:
# -*- coding: utf-8 -*def fonk():
a = 5
print a
fonk()
a = 10
print "a'nn de
geri: ", a
Buradaki ilk 5 says fonksiyon iindeki ann degerini gsteriyor. Alt satrdaki 10 degeri
ise ann fonksiyon snrlar dsndaki degerini... Grdgnz gibi, a degiskenini fonksiyon
dsnda da kullanabilmek iin bu degiskeni dsarda tekrar tanmlamamz gerekiyor. Peki, biz
fonksiyon iindeki a degiskenine fonksiyon dsndan da erisemez miyiz? Elbette
erisebiliriz. Ama bunun iin global adl bir deyimden yararlanmamz gerekir. Dilerseniz
yukarda ilk verdigimiz rnek zerinden giderek bu global deyimini anlamaya alsalm:
# -*- coding: utf-8 -*def fonk():
a = 5
print a
fonk()
print "a'nn de
geri: ", a
Kodlar bu sekilde yazdgmzda Pythonun bize bir hata mesaj gsterecegini biliyoruz. Simdi
83
Burada yaptgmz sey, fonksiyonu tanmladktan sonra fonksiyon gvdesinin ilk satrna
global a diye bir sey eklemekten ibaret. Bu ifade fonksiyon iindeki a adl degiskenin
global oldugunu, yani fonksiyonun kendi snrlar dsnda da geerli bir deger oldugunu
sylyor. Bu kodlar alstrdgmzda syle bir kt alyoruz:
5
a'nn de
geri: 5
Grdgnz gibi, global deyimi bir fonksiyon iindeki degerlere fonksiyon dsndan da
erismemize yardmc oluyor...
Simdi
Buradaki return deyimine taklmayn biraz sonra bunun tam olarak ne ise yaradgn
grecegiz. Biz yalnzca yukardaki kodlarn ktsna odaklanalm.
Burada ncelikle bir a degiskeni tanmladk. Bu degiskenin degeri 10. Ardndan bir
fonk() adl bir fonksiyon olusturduk. Bu fonksiyon iinde degeri 5 olan bir a degiskeni
daha tanmladk. Fonksiyon dsnda ise, iki adet kt veriyoruz. Bunlardan ilki fonksiyon
iindeki a degiskeninin degerini gsteriyor. Ikincisi ise fonksiyon dsndaki a
degiskeninin degerini... Yani bu kodlar alstrdgmzda syle bir kt elde ediyoruz:
a'nn fonksiyon iindeki de
geri 5
a'nn fonksiyon d
sndaki de
geri: 10
Burada fonksiyon iinde ve dsnda ayn adda iki degisken tanmlamamza ragmen,
Pythondaki isim alan kavram sayesinde bu iki degiskenin degeri birbirine karsmyor.
Ama bir de su kodlara bakn:
# -*- coding: utf-8 -*a = 10
def fonk():
global a
a = 5
return a
print "a'nn fonksiyon iindeki de
geri", fonk()
print "a'nn fonksiyon d
sndaki de
geri: ", a
Burada bir nceki kodlara ilave olarak global a satrn yazdk. Bu defa ktmz syle oldu:
84
bu
noktada kendimize su soruyu sormamz lazm: Acaba bizim istedigimiz sey bu mu? zellikle
zerinde birka farkl kisinin alstg byk projelerde byle bir zellik ne tr sorunlara yol
aabilir? zerinde pek ok farkl kisinin alstg byk projelerde global deyiminin byk
skntlar dogurabilecegi apak ortada. Siz programn bir yerine bir degisken tanmlamaya
alsrken, baska bir gelistirici bir fonksiyon iinde global deyimini kullanarak fonksiyon
dsndaki ayn adl degiskenlerin degerini birbirine katms olabilir... Iste bu tr skntlardan
tr, her ne kadar faydal bir arams gibi grnse de, global deyiminin sakncalar
faydalarndan oktur. O yzden yazdgnz programlarda global deyiminden mmkn
oldugunca uzak durmanzda fayda var.
Dikkat ederseniz burada return diye bir sey kullandk. Bu kelime Trkede vermek,
dndrmek, iade etmek gibi anlamlara gelir. Buna gre yukardaki fonksiyon a degiskenini
dndryor... Peki bu ne demek? Aklayalm:
Pythonda her fonksiyonun bir dns degeri vardr. Yani Pythondaki btn fonksiyonlar bir
deger dndrr. Burada dndrmekten kastmz: bir islemin sonucu olarak ortaya kan
degeri vermektir. Mesela, Bu fonksiyonun dns degeri bir karakter dizisidir. veya Bu
fonksiyon bir karakter dizisi dndrr. dedigimiz zaman kastettigimiz sey; bu fonksiyonun
isletilmesi sonucu ortaya kan degerin bir karakter dizisi oldugudur. rnegin yukardaki
fonksiyon a adl degiskeni dndryor ve bu a degiskeni bir tamsay oldugu iin,
fonksiyonumuzun dns degeri bir tamsaydr. Peki, fonksiyonlar bir deger dndryor da ne
oluyor? Yani bir fonksiyonun herhangi bir deger dndrmesinin kime ne faydas var?
Isterseniz bunu daha iyi anlayabilmek iin yukardaki rnegi bir de syle yazalm:
def fonk():
a = 5
print a
Burada herhangi bir deger dndrmyoruz. Yaptgmz sey bir a degiskeni belirleyip, print
deyimini kullanarak bunu ekrana bastrmaktan ibaret. Bu arada sunu da belirtelim: Her ne
kadar biz bir fonksiyonda ak ak bir deger dndrmesek de o fonksiyon otomatik olarak bir
deger dndrecektir. Herhangi bir deger dndrmedigimiz fonksiyonlar otomatik olarak
None diye bir deger dndrr. Bunu su sekilde test edebiliriz:
Yukardaki fonksiyonu su sekilde agralm:
85
print fonk()
Iste burada grdgmz None degeri, fonk() adl fonksiyonumuzun otomatik olarak
dndrdg degerdir.
Yukardaki fonksiyonu print olmadan da agrabilecegimizi biliyorsunuz:
fonk()
su fonksiyona bakalm:
def fonk():
a = 5
return a
fonk()
Burada ise ekranda herhangi bir kt gremeyiz. Bunun nedeni, bu fonksiyonda herhangi bir
print islemi yapmyor olmamzdr. Biz burada sadece a degiskenini dndrmekle
yetiniyoruz. Yani ekrana herhangi bir kt vermiyoruz. Bu fonksiyondan kt alabilmek iin
fonksiyonu syle agrmamz gerekir:
print fonk()
86
5
a de
gi
skeninin de
geri: None
Burada sayi_isle() adl fonksiyonda kullancya bir say sorup bu sayy dndryoruz. Daha
sonra fonksiyonu agrrken, bu dndrdmz degerle istedigimiz islemi yapabiliyoruz.
Isterseniz bu fonksiyonu bir de return yerine print ile tanmlamay deneyin. O zaman ne
demek istedigimi gayet net bir biimde anlayacaksnz...
87
#!/usr/bin/python
# -*- coding: utf-8 -*def deneme():
liste = []
while True:
a = raw_input("Giriniz: ")
if a == "0":
pass
else:
liste.append(a)
print liste
deneme()
Burada grdgmz gibi, eger kullanc 0 degerini girerse, bu deger listeye eklenmeyecek,
Python hibir sey yapmadan bu satr atlayacaktr. Iste pass buna benzer durumlarda, hibir
sey yapmadan yola devam et! anlam katar kodlarmza.
pass deyimini yukardaki durumlar dsnda bir de syle bir durumda kullanabilirsiniz: Diyelim
ki bir program yazyorsunuz. Bu programda bir fonksiyon tanmlayacaksnz. Fonksiyonun
isminin ne olacagna karar verdiniz, ama fonksiyon ierigini nasl yazacagnz dsnmediniz.
Eger program iinde sadece fonksiyonun ismini yazp brakrsanz programnz alsma
srasnda hata verecektir. Iste byle bir durumda pass deyimi imdadnza yetisir. Bu deyimi
kullanarak syle bir sey yazabilirsiniz:
def bir_fonksiyon():
pass
88
BLM 6
Modller
89
Bu program iinde carp() fonksiyonuna ihtiyacnz oldugunda yapmanz gereken tek sey bu
fonksiyonu agrmaktr. Bu islemi nasl yapacagmz bir nceki blmde tartsmstk. Ayn
fonksiyona baska bir programda da ihtiya duymamz halinde yine yapacagmz sey bu
fonksiyonu o program iinden agrmak olacak. Ancak bunu yapmann belli kurallar var.
Peki, nedir bu kurallar?
ncelikle Modl nedir? sorusunu tekrar soralm. Bu blmn en basnda yaptgmz tanma
gre, carp() fonksiyonunu ieren yukardaki deneme.py adl program bir modldr. Bu
modln ad da denemedir. Pythonda modller .py uzantsna sahiptir. Ancak bir modln
ad sylenirken bu .py uzants es geilir ve sadece isim ksm dikkate alnr. Bu yzden
elinizdeki deneme.py adl programn (ya da modln) ad deneme olacaktr. Simdi
bu
deneme.py adl dosyann bulundugu dizin iinde bir komut satr ap Pythonun etkilesimli
kabugunu alstrn. Mesela eger deneme.py dosyasn masastne kaydettiyseniz bir komut
satr an, cd Desktop komutuyla masastne gelin ve python komutunu vererek etkilesimli
kabugu baslatn. Simdi
su komutu verin:
>>> import deneme
Eger hibir sey olmadan bir alt satra geildiyse modlnz basaryla ie aktardnz demektir.
Eger No module named deneme gibi bir hata mesajyla karslasyorsanz, muhtemelen
Pythonu masastnn oldugu dizinde baslatamamssnzdr.
import deneme komutunun basarl oldugunu varsayarak yolumuza devam edelim...
Modl ie aktardktan sonra dir() adl zel bir fonksiyondan yararlanarak, ie aktardgmz
bu modl iindeki kullanlabilir fonksiyon ve nitelikleri grebiliriz:
>>> dir(deneme)
90
Blm 6. Modller
Burada bizi ilgilendiren ksm en sondaki carp adl ge. Bu ktdan anlyoruz ki, deneme
adl modln iinde carp adl bir fonksiyon var ve biz bu fonksiyonu kullanma imknna
sahibiz. O halde gelin bu fonksiyonu kullanmak iin srasyla syle bir seyler yazalm:
>>> liste = [45, 66, 76, 12]
>>> deneme.carp(liste)
Grdgnz gibi, deneme modl iindeki carp() adl fonksiyonu kullanarak liste
iindeki saylar birbiriyle arptk. deneme modln nasl ie aktardgmza ve bu modln
iindeki bir fonksiyon olan carp() fonksiyonunu nasl kullandgmza ok dikkat edin. nce
modlmzn ad olan denemeyi yazyoruz. Ardndan bir nokta isareti koyup, ihtiyacmz
olan fonksiyonun adn belirtiyoruz. Yani syle bir forml takip ediyoruz:
modl_ad.fonksiyon
Bylece modl iindeki fonksiyona erismis olduk... Yalnz burada asla unutmamamz gereken
sey ncelikle kullanacagmz modl import modl_ad komutuyla ie aktarmak olacaktr.
Modl ie aktarmazsak tabii ki o modldeki fonksiyon veya niteliklere erisemeyiz...
Simdi
Simdi
Bu komut biraz ncekiyle ayn kty verecektir. Halbuki biz modlmze a adl bir
degisken daha ekledik. O halde neden bu degisken listede grnmyor? Pythonda bir modl
ie aktardktan sonra eger o modlde bir degisiklik yaparsanz, o degisikligin etkili olabilmesi
iin modl yeniden yklemeniz gerekir. Bu islemi reload() adl zel bir fonksiyon yardmyla
yapyoruz:
91
>>> reload(deneme)
dir(deneme) komutunu
tekrar verelim:
>>> dir(deneme)
92
Blm 6. Modller
>>> carp(liste)
24
Grdgnz gibi, bu defa deneme.carp(liste) gibi bir komut vermedik. carp() fonksiyonunu
dogrudan kullanabildik. Bu yntem olduka pratiktir. Programcya ayn isi daha az kodla
yapma imkn saglar. Ancak bu yntemin baz sakncalar vardr. Bunlara biraz sonra
deginecegiz.
Mesela ie aktaracagnz modl ad ok uzunsa ve her defasnda bu uzun ismi yazmak size zor
geliyorsa bu yntemi kullanarak modl adn ksaltabilirsiniz. Ayrca programnzda zaten
deneme adl baska bir nitelik veya fonksiyon varsa bu ikisinin birbirine karsmasn
engellemek iin de bu yntemi kullanmay tercih edebilirsiniz.
Peki bu yntemlerden hangisini kullanmak daha iyidir? Eger ne yaptgnzdan tam olarak
emin degilseniz veya o modlle ilgili bir belgede farkl bir yntem kullanmanz nerilmiyorsa,
anlatlan birinci yntemi kullanmak her zaman daha gvenlidir (import modl_ad). nk bu
sekilde bir fonksiyonun nereden geldigini karstrma ihtimaliniz ortadan kalkar. Mesela
6.1. Modlleri Ie Aktarma (importing Modules)
93
deneme.carp(liste) gibi bir komuta baktgnzda carp() fonksiyonunun deneme adl bir
modl iinde oldugunu anlayabilirsiniz. Ama sadece carp(liste) gibi bir komutla
karslastgnzda bu fonksiyonun program iinde mi yer aldgn, yoksa baska bir modlden mi
ie aktarldgn anlayamazsnz. Ayrca mesela programnz iinde zaten carp adl bir
fonksiyon varsa, deneme adl modlden carp() fonksiyonunu aldgnzda isim aksmas
nedeniyle hi istemediginiz sonularla karslasabilirsiniz... Buna bir rnek verelim. Komut
satrnda syle bir kod yazn:
>>> a = 46
Simdi
6.2 os Modl
os adl modl Pythondaki en nemli modllerden biridir. Bu blmn en basnda yaptgmz
modl tanmn dikkate alacak olursak, aslnda os modl, bilgisayarmzda bulunan os.py
adl bir Python programdr... Peki biz bu os.py programn nereden bulabiliriz. GNU/Linux
sistemlerinde bu modl ogunlukla /usr/lib/python2.7/ dizini iinde bulunur. Windows
sistemlerinde ise bu modl bulmak iin C:/Python27/Lib adl dizinin iine bakabilirsiniz.
os modl bize, kullanlan isletim sistemiyle ilgili islemler yapma olanag sunar. Modln
kendi belgelerinde belirtildigine gre, bu modl kullanan programlarn farkl isletim
sistemleri zerinde alsma sans daha fazla. Bunun neden byle oldugunu biraz sonra daha
iyi anlayacaksnz.
Bu modl, yukarda anlattgmz sekilde ie aktaracagz:
94
Blm 6. Modller
>>> import os
Grdgnz gibi, kullanm olarak kendi yazdgmz bir modl nasl ie aktaryorsak os
modln de aynen yle ie aktaryoruz. Neticede bu modl siz de yazms olabilirdiniz.
Dolaysyla, ierigi dsnda, bu modln sizin yazdgnz herhangi bir Python programndan
(baska bir syleyisle Python modlnden) hi bir fark yoktur... Tabii bu modln sizin
yazdgnz modlden nemli bir fark, komut satrn hangi dizin altnda ams olursanz olun
os modln ie aktarabilmenizdir. Yani bu modl kullanabilmek iin os.py dosyasnn
bulundugu dizine gitmenize gerek yok. Bunun neden byle oldugunu biraz sonra
aklayacagz. O yzden bunu simdilik dert etmeyin. Neyse, biz konumuza dnelim...
Burada en nemli konu, bu modl ie aktarmaktr. Bu modln iindeki herhangi bir islevi
kullanabilmek iin ncelikle modl ie aktarmalyz. Eger bu sekilde modl import
etmezsek, bu modlle ilgili kodlarmz alstrmak istedigimizde Python bize bir hata mesaj
gsterecektir.
Bu modl programmz iine nasl davet edecegimizi grendigimize gre, os modl
iindeki fonksiyonlardan sz edebiliriz. ncelikle, isterseniz bu modl iinde neler var neler
yok syle bir listeleyelim...
Python komut satrnda >>> isaretinden hemen sonra:
>>> import os
Isterseniz daha anlaslr bir kt elde edebilmek iin bu komutu su sekilde de verebilirsiniz:
>>> for icerik in dir(os):
...
print icerik
Grdgnz gibi, bu modl iinde bir ygn fonksiyon ve nitelik var. Simdi
biz bu
fonksiyonlar ve niteliklerden nemli olanlarn incelemeye alsalm...
6.2. os Modl
95
if os.name == "nt":
a = raw_input("Bill Gates'e mesajnz yazn:")
print "Merhaba Windows Kullancs!"
Bu basit rnekte ncelikle os adl modl btn ierigiyle birlikte programmza aktardk.
Daha sonra bu modl iindeki name niteliginden yararlanarak, kullanlan isletim sistemini
sorguladk. Buna gre bu program alstrldgnda, eger kullanlan isletim sistemi
GNU/Linux ise, kullancdan Linus Torvaldsa mesajn yazmas istenecektir. Eger
kullanlan isletim sistemi Windows ise, Bill Gatese mesaj yazlmas istenecektir. os
modlnde isletim sistemi isimleri iin ntanml olarak su ifadeler bulunur:
GNU/Linux iin "posix",
Windows iin "nt", "dos", "ce"
Macintosh iin "mac"
OS/2 iin "os2"
Dikkat ederseniz burada from os import name komutuyla, os modl iindeki name niteligini
aldk yalnzca. Ayrca program iinde kullandgmz os.name ifadesini de name sekline
dnstrdk... nk from os import name komutuyla yalnzca name niteligini ektigimiz,
aslnda os modln ekmedigimiz iin, os.name yapsn kullanrsak Python bize os
isminin tanmlanmadgn syleyecektir.
Bu name niteliginin ne kadar faydal bir sey oldugunu tahmin edersiniz. Eger yazdgnz bir
programda name niteligini kullanarak isletim sistemi sorgulamas yaparsanz, yazdgnz
programn birden fazla isletim sistemi zerinde alsma imkn olacaktr. nk bu sayede
programnzn, kullanlan isletim sistemine gre islem yapmasn saglayabilirsiniz.
96
Blm 6. Modller
>>> import os
>>> a = os.listdir("/home/")
>>> print a
Hatta Pythondaki enumerate() adl zel bir fonksiyonu kullanarak bu islemi ok daha ksa bir
yoldan halledebilirsiniz:
import os
a = os.listdir("/home/")
for s, d in enumerate(a, 1):
print s, d
97
>>> import os
Grdgnz gibi bu komut bize o anda hangi dizin iinde bulundugumuzu sylyor. Bu arada
Ingilizce bilenler iin syleyelim, buradaki cwdnin alm current working directory.
Yani kabaca mevcut alsma dizini... Daha ak ifade etmek gerekirse: O anda iinde
bulundugumuz dizin. Syle
98
Blm 6. Modller
Buradaki pardir sabiti, Ingilizce parent directory (bir st dizin) ifadesinin ksaltmas oluyor.
pardir sabiti dsnda, bir de curdir sabiti vardr. Bu sabiti kullanarak mevcut dizin zerinde
islemler yapabiliriz:
>>> import os
>>> os.listdir(os.curdir)
Grdgnz gibi bu curdir sabiti getcwd() fonksiyonuna benziyor. Bunun dsnda, istersek
gitmek istedigimiz dizini kendimiz elle de belirtebiliriz:
>>> import os
>>> os.chdir("/var/tmp")
Bu kod / dizini altnda test adl bos bir klasr olusturacaktr. Eger bu kodu su sekilde
yazarsak, mevcut alsma dizini iinde yeni bir dizin olusacaktr:
>>> import os
>>> os.mkdir("test")
Yani, mesela mevcut alsma dizini masast ise bu test adl dizin masastnde
olusacaktr... Isterseniz bu kodlar su sekle getirerek yeni olusturulan dizinin nerede oldugunu
da grebilirsiniz:
>>> import os
>>> print os.getcwd()
>>> os.mkdir("test")
Bundan baska, eger isterseniz mevcut bir dizin yaps iinde baska bir dizin de
olusturabilirsiniz. Yani mesela /home/kullanc_adnz/ dizini iinde deneme adl bos bir
dizin olusturabilirsiniz:
>>> import os
>>> os.mkdir("/home/istihza/deneme")
6.2. os Modl
99
Peki diyelim ki i ie birka tane yeni klasr olusturmak istiyoruz. Yani mesela
/home/kullanc_adnz dizini altnda yeni bir Programlar dizini, onun altnda da Python
adl yeni baska bir dizin daha olusturmak istiyoruz. Hemen deneyelim:
>>> import os
>>> os.mkdir("/home/istihza/Programlar/Python")
Ne oldu? Syle
Demek ki bu sekilde oklu dizin olusturamyoruz. Iste bu ama iin elimizde makedirs()
fonksiyonu var. Hemen deneyelim yine:
>>> import os
>>> os.makedirs("/home/istihza/Programlar/Python")
Grdgnz gibi, /home/kullanc_admz/ dizini altnda yeni bir Programlar dizini ve onun
altnda da yeni bir Python dizini olustu. Buradan kan sonu, demek ki mkdir() fonksiyonu
bize yalnzca bir adet dizin olusturma izni veriyor.. Eger biz birden fazla, yani oklu yeni
dizin olusturmak istiyorsak makedirs() fonksiyonunu kullanmamz gerekiyor.
Kk bir rnek daha verip bu bahsi kapatalm:
>>> import os
>>> print os.getcwd()
>>> os.makedirs("test/test1/test2/test3")
Tahmin ettiginiz gibi bu kod mevcut alsma dizini altnda i ie test, test1, test2 ve
test3 adl dizinler olusturdu... Eger test ifadesinin soluna / isaretini eklerseniz, bu bos
dizinler kk dizini altnda olusacaktr...
Blm 6. Modller
>>> import os
>>> os.rmdir("/home/istihza/TEST")
Bu kodlar mevcut alsma dizini altnda test1 adl bir dizin ile bunun altnda test2 ve
test3 adl baska iki adet dizin daha olusturacaktr. Peki, bu test1, test2 ve test3
ifadelerinin sabit degil de degisken olmasn istersek ne yapacagz. Syle
import os
test1 = "Belgelerim"
test2 = "Hesaplamalar"
test3 = "Resimler"
os.makedirs(test1/test2)
os.makedirs(test1/test3)
6.2. os Modl
101
Bu komutu GNU/Linuxta verdigimiz iin komutun kts / seklinde oldu. Eger ayn
komutu Windowsta verirsek sonu syle olacaktr:
>>> import os
>>> os.sep
\
Peki bu os.sep niteligi ne ise yarar? Yazdgmz kodlarda dogrudan dizin ayrac vermek
yerine bu niteligi kullanrsak, programmz farkl isletim sistemlerinde alstrrken, sistemin
kendine zg dizin ayracnn kullanlmasn saglams oluruz... Yani mesela:
>>> import os
>>> os.makedirs("test/test2")
komutu yerine;
>>> import os
>>> os.makedirs("test" + os.sep + "test2")
import os
test1 = "Belgelerim"
test2 = "Hesaplamalar"
test3 = "Resimler"
os.makedirs(test1/test2)
os.makedirs(test1/test3)
ki:
>>> import os
>>> test1 = "Belgelerim"
>>> test2 = "Hesaplamalar"
102
Blm 6. Modller
>>>
>>>
>>>
>>>
test3 = "Resimler"
os.makedirs(test1)
os.makedirs(os.sep.join([test1, test2]))
os.makedirs(os.sep.join([test1, test3]))
Dikkat ederseniz, burada os.sep niteligini join() adl bir fonksiyon ile birlikte kullandk.
(join() fonksiyonunu birka ders sonra daha ayrntl bir sekilde inceleyecegiz). Yukardaki
kod sayesinde dogrudan / isaretine bulasmadan, basmz derde sokmadan isimizi
halledebiliyoruz. Ayrca burada parantez ve kseli parantezlerin nasl kullanldgna da dikkat
etmemiz gerekiyor...
Yukarda test1, test2 ve test3 degiskenlerinin adlarn dogrudan kod iinde verdik...
Tabii eger istersek raw_input() fonksiyonuyla dizin adlarn kullancya setirebilecegimiz
gibi, syle bir sey de yapabiliriz:
import os
def dizinler(test1, test2, test3):
os.makedirs(test1)
os.makedirs(os.sep.join([test1, test2]))
os.makedirs(os.sep.join([test1, test3]))
Dikkat ederseniz, burada ncelikle os modln agryoruz. Daha sonra dizinler adl bir
fonksiyon olusturup parametre olarak test1, test2 ve test3 adl degiskenler belirliyoruz.
Ardndan os.makedirs(test1) komutuyla test1 adl bir dizin olusturuyoruz. Tabii bu test1
bir degisken oldugu iin adn daha sonradan biz belirleyecegiz. Alttaki satrda ise
os.makedirs() ve os.sep.join() komutlar yardmyla, bir nceki satrda olusturdugumuz test1
adl dizinin iinde test2 adl bir dizin daha olusturuyoruz. Burada os.sep.join() fonksiyonu
/ isaretiyle ugrasmadan dizinleri birlestirme imkn saglyor bize. Hemen alttaki satrda da
benzer bir islem yapp kodlarmz bitiriyoruz. Bylece bir fonksiyon tanmlams olduk.
Simdi
Burada ncelikle import deneme satryla deneme adl modlmz agrdk. Daha sonra
deneme.dizinler satryla bu modl iindeki dizinler() adl fonksiyonu agrdk. Bylelikle
masastnde Belgelerim adl bir klasrn iinde Videolar ve Resimler adl iki klasr
olusturmus olduk. Bu os.sep.join() ifadesi ile ilgili son bir sey daha syleyip bu konuya bir
nokta koyalm.
Simdi
103
'Dizin1\\Dizin2'
Grdgnz gibi farkl platformlar zerinde, os.sep kts birbirinden farkl oluyor. Bu rnek,
os.sep niteliginin, yazdgmz programlarn tasnabilirligi (portability), yani farkl isletim
sistemleri zerinde alsabilme kabiliyeti asndan ne kadar nemli olabilecegini
gsteriyor...
Bu blmn basnda syle bir soru sormustuk: Acaba kendi yazdgmz modlleri ie
aktarabilmek iin modln bulundugu dizine gitmemiz gerekirken, os modln ie aktarmak
iin neden byle bir sey yapmamza gerek kalmyor? Simdi
Isterseniz
kendi gzlerimizle grelim:
>>> import sys
>>> sys.path
104
Blm 6. Modller
BLM 7
Dosya Islemleri
Bu blmde Python programlama dilini kullanarak dosyalar nasl ynetecegimizi, yani nasl
yeni bir dosya olusturacagmz, bir dosyaya nasl bir seyler yazabilecegimizi ve buna benzer
islemleri grenecegiz. Burada Pythonu kullanarak sistemimizde yeni dosyalar olusturmann
yansra, varolan dosyalar da, herhangi bir arac program kullanmadan dogrudan Python ile
aacagz.
Programclk yasamnz boyunca dosyalarla bol bol hasr nesir olacaksnz. O yzden bu
blm dikkatle takip etmenizi neririm. Isterseniz laf hi uzatmadan konumuza geelim.
Bu blmde amacmz bilgisayarmzda yeni bir dosya olusturmak. Anlamas daha kolay
olsun diye, Pythonla ilk dosyamz mevcut alsma dizini altnda olusturacagz. ncelikle
mevcut alsma dizinimizin ne oldugunu grelim. Hemen Python komut satrn ayoruz ve
su komutlar veriyoruz:
>>> import os
>>> os.getcwd()
Biraz sonra olusturacagmz dosya bu komutun kts olarak grnen dizin iinde olusacaktr.
Sayn ki bu dizin Masast (Desktop) olsun. Mevcut alsma dizinimizi de grendigimize gre
artk yeni dosyamz olusturabiliriz. Bu is iin open() adl bir fonksiyondan faydalanacagz.
Bu arada bir yanls anlaslma olmamas iin hemen belirtelim. Bu fonksiyonu kullanmak iin
os modlnn ie aktarlmasna gerek yok. Biraz nce os modln ie aktarmamzn nedeni
yalnzca getcwd() fonksiyonunu kullanmakt. Bu noktay da belirttikten sonra komutumuzu
veriyoruz:
>>> open("deneme_metni.txt", "w")
Bylelikle masastnde deneme_metni.txt adl bir metin dosyas olusturmus olduk. Simdi
verdigimiz bu komutu biraz inceleyelim. open() fonksiyonunun ne oldugu belli. Bir dosyay
amaya yaryor. Tabii ortada henz bir dosya olmadg iin burada amak yerine yeni bir
dosya olusturmaya yarad. Parantez iindeki deneme_metni.txtnin de ne oldugu ak.
Olusturacagmz dosyann adn trnak iine almay unutmuyoruz. Peki, bu w ne oluyor?
105
Pythonda dosyalar ynetirken, dosya izinlerini de belirtmemiz gerekir. Yani mesela bir
dosyaya yazabilmek iin w kipini (mode) kullanyoruz. Bu harf Ingilizcede yazma
anlamna gelen write kelimesinin ksaltmasdr. Bunun dsnda bir de r kipi ve a kipi
bulunur. r, Ingilizcede okuma anlamna gelen read kelimesinin ksaltmasdr.
r kipi, olusturulan veya alan bir dosyaya yalnzca okuma izni verildigini gsterir. Yani
bu dosya zerinde herhangi bir degisiklik yaplamaz. Degisiklik yapabilmek iin biraz nce
gsterdigimiz w kipini kullanmak gerekir. Bir de a kipi vardr, dedik. a da Ingilizcede
eklemek anlamna gelen append kelimesinden geliyor. a kipi nceden olusturdugumuz
bir dosyaya yeni veri eklemek iin kullanlr. Bu su anlama geliyor. rnegin
deneme_metni.txt adl dosyay w kipinde olusturup iine bir seyler yazdktan sonra tekrar
bu kiple ap iine bir seyler eklemek istersek dosya iindeki eski verilerin kayboldugunu
grrz. nk w kipi, ayn dosyadan bilgisayarnzda zaten var olup olmadgna
bakmakszn, ayn adda yepyeni bir dosya olusturacak, bunu yaparken de eski dosyay
silecektir. Dolaysyla dosya iindeki eski verileri koruyup bu dosyaya yeni veriler eklemek
istiyorsak a kipini kullanmamz gerekecek. Bu kiplerin hepsini sras geldiginde grecegiz.
Simdi
Bu arada dikkatli olun, dedigimiz gibi, eger bilgisayarnzda nceden deneme_metni.txt adl
bir dosya varsa, yukardaki komut size hi bir uyar vermeden eski dosyay silip zerine
yazacaktr.
Simdi
Dikkat ederseniz burada w kipi yerine r kipini kullandk. Biraz nce de akladgmz gibi
bu kip dosyaya okuma yetkisi verildigini gsteriyor. Yani eger biz bir dosyay bu kipte aarsak
dosya iine herhangi bir veri girisi yapma imknmz olmaz. Ayrca bu kip yardmyla yeni
bir dosya da olusturamayz. Bu kip bize varolan bir dosyay ama imkn verir. Yani mesela:
>>> ikincidosyam = open("deneme.txt", "r")
komutunu verdigimizde eger bilgisayarda deneme.txt adl bir dosya yoksa bu adla yeni bir
dosya olusturulmayacak, bunun yerine Python bize bir hata mesaj gsterecektir:
>>> f = open("deneme.txt")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 2] No such file or directory: 'deneme.txt'
Yukardaki rneklerde, yoktan bir dosya olusturmay ve halihazrda sistemimizde bulunan bir
106
dosyay amay grendik. Pythonda bir dosyay r kipinde atgmz zaman, o dosyay
yalnzca okuma hakk elde ediyoruz. Bu kiple atgmz bir dosya zerinde herhangi bir
degisiklik yapamayz. Eger bir dosyay w kipinde aarsak, Python belirttigimiz addaki
dosyay sfrdan olusturacak, eger ayn adla baska bir dosya varsa o dosyann zerine
yazacaktr. Pythonda dosya islemleri yaparken, ierigi dolu bir dosyay ap bu dosyaya
eklemeler yapmamz da gerekebilir. Iste byle durumlar iin a adl zel bir kipten
yararlanacagz. Bu kipi syle kullanyoruz:
>>> dosya = open("deneme_metni.txt", "a")
Pythonda bir dosyay a kipinde atgmz zaman, o dosyann iine yeni veriler ekleyebiliriz.
Ayrca a kipinin, r kipinin aksine bize yeni dosya olusturma imkn da verdiginiz
aklmzn bir ksesine not edelim.
Eger yazdgmz kod iinde yukardaki kipten hibirini kullanmazsak; Python, ntanml
olarak r kipini kullanacaktr. Tabii r kipinin yukarda bahsettigimiz zelliginden dolay,
bilgisayarmzda yeni bir dosya olusturmak istiyorsak, kip belirtmemiz, yani w veya a
kiplerinden birini kullanmamz gerekir. Bu arada, yukardaki rneklerde biz dosyamz
mevcut alsma dizini iinde olusturduk. Tabii ki siz isterseniz tam yolu belirterek, dosyanz
istediginiz yerde olusturabilirsiniz. Mesela:
>>> dosya = open("/home/kullanc_ad/deneme.txt","w")
komutu /home/kullanc_ad/ dizini altnda, yazma yetkisi verilmis, deneme.txt adl bir dosya
olusturacaktr.
Yalnz burada kk bir uyar yapalm. Yazdgmz kodlarda yol ad belirtirken kullandgmz
yatk izgilerin ynne dikkat etmemiz gerekir. En emin yol, yukarda yaptgmz gibi dosya
yolunu saga yatk bl isaretiyle ayrmaktr:
>>> dosya = open("/home/kullanc_ad/deneme.txt","w")
Saga yatk bl btn isletim sistemlerinde sorunsuz alsr. Ama sola yatk bl problem
yaratabilir:
>>> f = open("C:\Documents and Settings\fozgul\Desktop\filanca.txt", "a")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 22] invalid mode ('a') or filename: 'C:\\\\Documents and
Settings\\x0cozgul\\\\Desktop\\x0cilanca.txt'
Burada sorun, Pythonun \ isaretini bir kas dizisi olarak alglamas. Halbuki biz burada bu
isareti yol ayrac olarak kullanmak istedik... Eger saga yatk bl kullanmak isterseniz \
isaretini iftlemeniz gerekir:
>>> f = open("C:\\Documents and Settings\\fozgul\\Desktop\\filanca.txt", "a")
Bylece dosya yolunu olusturan karakter dizisi iindeki kas dizilerini islevsiz hale getirerek
Pythonn hata vermesini engelleyebilirsiniz.
7.1. Dosya Olusturmak
107
Grdgnz gibi bu kez dosyamz a kipiyle atk. Zaten w kipiyle aarsak eski dosyay
silmis oluruz. O yzden Pythonla programlama yaparken bu tr seylere ok dikkat etmek
gerekir.
Dosyamz a kipiyle atktan sonra write() fonksiyonu yardmyla Monty Python satrn
eski dosyaya ekledik. Burada \n adl kas dizisinden yararlandgmza da dikkat edin. Eger
bunu kullanmazsak eklemek istedigimiz satr bir nceki satrn hemen arkasna getirilecektir.
Btn bunlardan sonra da close() fonksiyonu yardmyla dosyamz kapattk. Bir de su rnege
108
bakalm:
#!/usr/bin/env python
# -*- coding: utf-8
dosya = open("
siir.txt", "w")
dosya.write("Btn gne
sler batmadan,\nBi trk daha \
syleyeyim bu yerde\n\t\t\t\t --Orhan Veli--")
dosya.close()
Grdgnz gibi, siir adl bir metin dosyas olusturup bu dosyaya yazma yetkisi verdik.
Bu dosyann iine yazlan verilere ve burada kas dizilerini nasl kullandgmza ok dikkat
edin. Ikinci msray bir alt satra almak iin \n kas dizisini kullandk. Daha sonra Orhan
Veli satrn sayfann sagna dogru kaydrmak iin \t kas dizisinden yararlandk. Bu
rnekte \n ve \t kas dizilerini yan yana kullandk. Bylece ayn cmleyi hem alt satra
alms, hem de saga dogru kaydrms olduk. Ayrca birka tane \t kas dizisini yan yana
kullanarak cmleyi sayfann istedigimiz noktasna getirdik.
Yukardaki write() fonksiyonu dsnda ok yaygn kullanlmayan bir de writelines()
fonksiyonu vardr. Bu fonksiyon birden fazla satr bir kerede dosyaya islemek iin kullanlr.
Syle
ki:
#!/usr/bin/env python
# -*- coding: utf-8
dosya = open("
siir2.txt", "w")
dosya.writelines(["Bilmezler yalnz ya
samayanlar\n",
"Nasl korku verir sessizlik insana\n",
"
Insan nasl konu
sur kendisiyle\n",
"Nasl ko
sar aynalara bir cana hasret\n",
"Bilmezler...\n"])
dosya.close()
Burada parantez iindeki kseli parantezlere dikkat edin. Aslnda olusturdugumuz sey bir
liste. Dolaysyla bu fonksiyon bir listenin ierigini dogrudan bir dosyaya yazdrmak iin
faydal olabilir. Ayn kodu write() fonksiyonuyla yazmaya kalksrsanz alacagnz sey bir hata
mesaj olacaktr. Eger bir liste iinde yer alan geleri write() fonksiyonunu kullanarak
dosyaya yazdrmak isterseniz for dngsnden yararlanabilirsiniz:
>>> liste = ["elma", "armut", "kalem"]
>>> f = open("falanca.txt", "w")
>>> for i in liste:
...
f.write(i+"\n")
...
>>> f.close()
109
kadar nasl yeni bir dosya olusturacagmz, bu dosyaya nasl veri girecegimizi ve bu
dosyay nasl kapatacagmz grendik. Simdi
yeni = open("
siir.txt","w")
yeni.write("Sular ekilmeye ba
slad \
kklerden...\nIsnmaz m acaba ellerimde kan? \
\nAh,ne olur! Btn gne
sler batmadan\nBi trk \
daha syleyeyim bu yerde...")
>>> yeni.close()
>>> yeni = open("
siir.txt")
>>> print yeni.read()
Sular ekilmeye ba
slad kklerden...
Isnmaz m acaba ellerimde kan?
Ah, ne olur! Btn gne
sler batmadan
Bi trk daha syleyeyim bu yerde...
yeni.read() satrna kadar olan ksm zaten biliyoruz. Burada kullandgmz read() fonksiyonu
yeni adl degiskenin ierigini okumamz saglyor. yeni adl degiskenin degeri siir.txt adl bir
dosya oldugu iin, bu fonksiyon siir.txt adl dosyann ierigini bize gsterecektir.
Ayrca read() dsnda bir de readlines() adl bir fonksiyon bulunur. Eger yukardaki komutu:
>>> yeni.readlines()
seklinde bir kod yazarsak, dosya ieriginin yalnzca ilk satr okunacaktr. Pythonun
readline() fonksiyonunu degerlendirirken kullandg lt sudur: Dosyann basndan itibaren
ilk \n ifadesini grdgn yere kadar oku. Bunlarn dsnda, eger istersek bir for dngs
kurarak da dosyamz okuyabiliriz:
>>> yeni = open("
siir.txt")
>>> for satir in yeni:
...
print satir
Dikkat ettiyseniz:
>>> print yeni.readlines()
veya alternatif komutlarla dosya ierigini okurken syle bir sey oluyor. Mesela iinde;
110
Birinci satr
Ikinci satr
nc satr
komutuyla bu dosyann ilk satrn okuyalm. Daha sonra tekrar bu komutu verdigimizde
birinci satrn degil, ikinci satrn okundugunu grrz. nk Python ilk okumadan sonra
imleci (Evet, biz grmesek de aslnda Pythonun dosya iinde gezdirdigi bir imle var.)
dosyada ikinci satrn basna kaydryor. Eger bir daha verirsek bu komutu, nc satr
okunacaktr. Son bir kez daha bu komutu verirsek, artk dosyann sonuna ulasldg iin,
ekrana hi bir sey yazlmayacaktr. Byle bir durumda dosyay basa sarmak iin su
fonksiyonu kullanyoruz. (Dosyamzn adnn dosya oldugunu varsayyoruz):
>>> dosya.seek(0)
Bylece imleci tekrar dosyann en basna alms olduk. Tabii siz isterseniz, bu imleci farkl
noktalara da tasyabilirsiniz. Mesela:
>>> dosya.seek(10)
komutu imleci 10. karakterin basna getirecektir (Saymaya her zamanki gibi 0dan
baslyoruz.) Bu seek() fonksiyonu aslnda iki adet parametre alabiliyor. Syle
ki:
>>> dosya.seek(5, 0)
komutu imleci dosyann basndan itibaren 5. karakterin bulundugu noktaya getirir. Burada 5
says imlecin kaydrlacag noktay, 0 says ise bu islemin dosyann basndan sonuna dogru
olacagn, yani saymaya dosyann basndan baslanacagn gsteriyor:
>>> dosya.seek(5, 1)
komutu imlecin o anda bulundugu konumdan itibaren 5. karakterin oldugu yere ilerlemesini
saglar. Burada 5 says yine imlecin kaydrlacag noktay, 1 says ise imlecin o anda
bulundugu konumun lt alnacagn gsteriyor.
Son olarak:
>>> dosya.seek(-5,2)
komutu ise saymaya tersten baslanacagn, yani dosyann basndan sonuna dogru degil de
sonundan basna dogru ilerlenerek, imlecin sondan 5. karakterin oldugu yere getirilecegini
gsterir.
Bu ifadeler biraz karsk gelmis olabilir. Bu konuyu anlamann en iyi yolu bol bol uygulama
yapmak ve deneyerek grmektir. Isterseniz, yukardaki okuma fonksiyonlarna da belirli
parametreler vererek dosya iinde okunacak satrlar veya karakterleri belirleyebilirsiniz.
Mesela:
>>> yeni.readlines(3)
111
komutu dosya iinde, imlecin o anda bulundugu noktadan itibaren 3. karakterden sonrasn
okuyacaktr. Peki, o anda imlecin hangi noktada oldugunu nereden bilecegiz? Pythonda bu
islem iin de bir fonksiyon bulunur:
>>> dosya.tell()
komutu yardmyla imlecin o anda hangi noktada bulundugunu grebilirsiniz. Hatta dosyay
bir kez:
>>> dosya.read()
komutunu verirseniz imle mevcut dosyann en sonuna gelecegi iin, ekranda grdgnz
say ayn zamanda mevcut dosyadaki karakter saysna esit olacaktr.
Pythonda dosya islemleri yaparken bilmemiz gereken en nemli noktalardan biri de sudur:
Python ancak karakter dizilerini (strings) dosyaya yazdrabilir. Saylar yazdramaz. Eger biz
saylar da yazdrmak istiyorsak nce bu saylar karakter dizisine evirmemiz gerekir. Bir
rnek verelim:
>>> x = 50
>>> dosya = open("deneme.txt", "w")
>>> dosya.write(x)
Grdgnz gibi Python bize bir hata mesaj gsterdi. nk x degiskeninin degeri bir say.
Halbuki karakter dizisi olmas gerekiyor. Bu meseleyi zmek iin komutumuzu su sekilde
veriyoruz. En bastan alrsak:
>>> x = 50
>>> dosya = open("deneme.txt", "w")
>>> dosya.write(str(x))
Burada:
>>> str(x)
>>> os.remove("dosya/yolu")
Eger masast zaten sizin mevcut alsma dizininiz ise bu islem ok daha basittir:
>>> import os
>>> os.remove("deneme.txt")
kadar hep dosya sonuna satr ekledik. Peki ya bir dosyann ortasna bir yere satr
eklemek istersek ne yapacagz? Simdi:
Ikinci Satr
nc Satr
Drdnc Satr
Be
sinci Satr
Biz burada Ikinci Satr ile nc Satr arasna Merhaba Python! yazmak istiyoruz. nce
bu deneme.txt adl dosyay aalm:
>>> kaynak = open("deneme.txt")
Bu dosyay ise yazma modunda atk. nk kaynak dosyadan okudugumuz verileri buraya
yazdracagz. Simdi
Bylece kaynak dosya zerinde yapacagmz satr okuma islemini de tanmlams olduk...
Simdi
kaynak dosyadaki birinci satr ve ikinci satr verilerini alp hedef dosyaya yazdryoruz.
Bu is iin bir for dngs olusturacagz:
>>> for satirlar in oku[:2]:
...
hedef.write(satirlar)
113
Bu noktadan sonra eger istersek kaynak dosyay silip adn da hedef dosyann adyla
degistirebiliriz:
>>> os.remove("deneme.txt")
>>> os.rename("test.txt","deneme.txt")
/>
/>
/>
/>
/>
114
Simdi
yapmamz gereken sey, gerekli bilgileri dosyaya yazmak olacak. O yzden bu defa
falanca.xml adl dosyay yazma kipinde ayoruz:
yaz = open("falanca.xml", "w")
/>
/>
/>
/>
/>
115
Simdi
Burada da, tpk bir nceki blmde oldugu gibi, ncelikle readlines() metodunu kullanarak
dosya ierigini bir listeye gnderdik. Daha sonra bu listede silmek istedigimiz satra karslk
gelen genin sra numarasn kullanarak del deyimi yardmyla ilgili geyi listeden kaldrdk.
Son olarak da elimizdeki degistirilmis listeyi bir dosyaya yazdrdk.
Grdgnz gibi bir dosyaya veri girmek veya dosyadan veri karmak son derecek kolay bir
islem. Yapmamz gereken tek sey dosya ierigini bir listeye alp, bu liste zerinde gerekli
degisiklikleri yapmak. Daha sonra da bu degistirilmis listeyi dosyaya yazdrararak amacmza
ulasabiliyoruz.
116
BLM 8
Hata Yakalama
Gayet basit bir program bu, degil mi? Bu program grnste herhangi bir kusur tasmyor.
Eger kullancmz burada bizim istedigimiz gibi bir say girerse bu programda hibir sorun
kmaz. Programmz grevini basaryla yerine getirir.
Peki ama ya kullanc say yerine harf girerse ne olacak? Mesela kullanc yukardaki
program alstrp a harfine basarsa ne olur?
Byle bir durumda programmz syle bir hata mesaj verir:
Traceback (most recent call last):
File "deneme.py", line 4, in <module>
sayi = int(raw_input("Ltfen bir say girin: "))
ValueError: invalid literal for int() with base 10: 'a'
Grdgnz gibi, ortaya kan hata nedeniyle programn son satr ekrana baslamad. Yani
programmz hata yznden ktg iin islem yarda kald.
Burada byle bir hata almamzn nedeni, kullancdan say bekledigimiz halde kullancnn
harf girmesi. Biz yukardaki programda int() fonksiyonunu kullanarak kullancdan aldgmz
karakter dizilerini sayya dnstrmeye alsyoruz. Mesela kullanc 23 degerini girerse bu
karakter dizisi rahatlkla sayya dnstrlebilir. Dilerseniz bunu etkilesimli kabukta test
edelim:
117
>>> int("23")
23
Grdgnz gibi 23 adl karakter dizisi rahatlkla sayya dnstrlebiliyor. Peki ya su?
>>> int("a")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'a'
Iste bizim programmzn yapmaya alstg sey de tam olarak budur. Yani programmz
kullancdan aldg a harfini sayya dnstrmeye alsyor ve tabii ki basarsz oluyor.
Bir kod yazarken, yazlan kodlar isletecek kullanclar her zaman gz nnde bulundurmanz
gerektigini asla unutmayn. Program alstrlrken kullanclarn ne gibi hatalar
yapabileceklerini kestirmeye alsn. nk kullanclar her zaman sizin istediginiz gibi
davranmayabilir. Siz programn yazar olarak, kodlarnz tandgnz iin programnz nasl
kullanmanz gerektigini biliyorsunuzdur, ama son kullanc byle degildir.
Yukardaki kodun, ok uzun bir programn paras oldugunu dsnrsek, kullancnn yanls
veri girisi koskoca bir programn kmesine veya durmasna yol aabilir. Bu tr durumlarda
Python gerekli hata mesajn ekrana yazdrarak kullancy uyaracaktr, ama tabii ki Pythonun
sundugu karmask hata mesajlarn kullancnn anlamasn bekleyemeyiz. Bylesi durumlar
iin Pythonda try... except ifadeleri kullanlr. Iste biz de bu blmde bu tr ifadelerin ne
zaman ve nasl kullanlacagn anlamaya alsacagz.
de byle bir hata ortaya karsa ne yapacagmza karar vermemiz gerekiyor. Mesela
yle bir durumda kullancya, Ltfen harf degil, say girin! gibi bir uyar mesaj
gsterebiliriz. Dilerseniz bu dediklerimizi somutlastralm. Kodlarmzn ilk hali syleydi:
118
#!/usr/bin/env python
# -*- coding: utf-8 -*sayi = int(raw_input("Ltfen bir say girin: "))
print "Girdi
giniz say", sayi
print "Te
sekkrler. Ho
sakaln!"
suna bakn:
#!/usr/bin/env python
# -*- coding: utf-8 -*try:
sayi = int(raw_input("Ltfen bir say girin: "))
print "Girdi
giniz say", sayi
except ValueError:
print "Ltfen harf de
gil, say girin!"
print "Te
sekkrler. Ho
sakaln!"
Burada, hata verecegini bildigimiz kodlar bir try... blogu iine aldk. Ardndan bir except
blogu aarak, ne tr bir hata bekledigimizi belirttik. Buna gre, bekledigimiz hata tr
ValueError. Son olarak da hata durumunda kullancya gsterecegimiz mesaj yazdk. Artk
kullanclarmz say yerine harfe basarsa programmz kmeyecek, aksine alsmaya devam
edecektir. Dikkat ederseniz print Tesekkrler. Hosakaln! satr her kosulda ekrana
baslyor. Yani kullanc dogru olarak say da girse, yanlslkla say yerine harf de girse
programmmz yapmas gereken islemleri tamamlayp yoluna devam edebiliyor.
Konuyu daha iyi anlayabilmek iin bir rnek daha verelim. Simdi
Eger burada kullanc ikinci sayya 0 cevab verirse programmz syle bir hata mesaj verip
kecektir. nk bir say 0a blnemez:
Traceback (most recent call last):
File "deneme.py", line 7, in <module>
sonuc = float(ilk) / ikinci
ZeroDivisionError: float division
Byle bir durumda hata alacagmz bildigimize gre ilk adm olarak ne tr bir hata mesaj
8.1. try... except...
119
de byle bir hata durumunda ne yapacagmza karar vermemiz gerekiyor. Isterseniz yine
kullancya bir uyar mesaj gsterelim.
Kodlarmz yazyoruz:
#!/usr/bin/env python
# -*- coding: utf-8 -*ilk = int(raw_input("Blme i
slemi iin ilk sayy girin: "))
ikinci = int(raw_input("
Simdi de ikinci sayy girin: "))
try:
sonuc = float(ilk) / ikinci
print sonuc
except ZeroDivisionError:
print "Ltfen sayy 0'a blmeye al
smayn!"
Bir nceki rnekte de yaptgmz gibi burada da hata verecegini bildigimiz kodlar try... blogu
iine aldk. Byle bir durumda alnacak hatann ZeroDivisionError oldugunu da bildigimiz
iin except blogunu da buna gre yazdk. Son olarak da kullancya gsterilecek uyary
belirledik. Bylece programmz hata karssnda kmeden yoluna devam edebildi.
Burada nemli bir problem dikkatinizi ekmis olmal. Biz yukardaki kodlarda, kullancnn
bir sayy 0a blmesi ihtimaline kars ZeroDivisionError hatasn yakaladk. Ama ya kullanc
say yerine harf girerse ne olacak? ZeroDivisionError ile birlikte ValueErroru da
yakalamamz gerekiyor... Eger yukardaki kodlar alstran bir kullanc say yerine harf
girerse syle bir hatayla karslasr:
Traceback (most recent call last):
File "deneme.py", line 4, in <module>
ilk = int(raw_input("Blme i
slemi iin ilk sayy girin: "))
ValueError: invalid literal for int() with base 10: 'a'
120
Grdgnz gibi hata verecegini bildigimiz kodlarn hepsini bir try... blogu iine aldk.
Ardndan da verilecek hatalar birer except blogu iinde teker teker yakaladk. Eger her iki
hata iin de ayn mesaj gstermek isterseniz syle bir sey yazabilirsiniz:
#!/usr/bin/env python
# -*- coding: utf-8 -*try:
ilk = int(raw_input("Blme i
slemi iin ilk sayy girin: "))
ikinci = int(raw_input("
Simdi de ikinci sayy girin: "))
sonuc = float(ilk) / ikinci
print sonuc
except (ZeroDivisionError, ValueError):
print "Girdi
giniz veri hatal!"
Hata trlerini nasl grupladgmza dikkat edin. Hatalar birbirinden virglle ayrp parantez
iine alyoruz... Bylece programmz her iki hata tr iin de ayn uyary gsterecek
kullancya.
Bu blm, hata yakalama konusuna iyi bir giris yapmamz saglad. Ilerde ok daha farkl hata
trleriyle karslastgnzda bu konuyu ok daha net bir sekilde iinize sindirmis olacaksnz.
Isterseniz simdi bu konuyla baglantl oldugunu dsndgmz, nemli bir deyim olan passi
inceleyelim.
121
else:
pass
Burada henz else blogunda ne yaplacagna karar vermemis oldugunuz iin, oraya bir pass
koyarak durumu simdilik geistiriyorsunuz. Program son haline gelene kadar oraya bir seyler
yazms olacagz.
Szn z, pass deyimlerini, herhangi bir islem yaplmasnn gerekli olmadg durumlar iin
kullanyoruz. Ilerde ise yarar programlar yazdgnzda, bu pass deyiminin grndgnden
daha faydal bir ara oldugunu anlayacaksnz.
122
BLM 9
Mevcut metotlar listelemek iin birka farkl yntemden faydalanabiliriz. Bunlardan ilki
syle olabilir:
>>> dir(str)
Burada dir() fonksiyonuna parametre (argman) olarak str adn geiyoruz. str,
Ingilizcede karakter dizisi anlamna gelen string kelimesinin ksaltmas oluyor. Yeri
gelmisken syleyelim: Eger karakter dizileri yerine listelerin metotlarn listelemek isterseniz
kullanacagnz biim su olacaktr:
>>> dir(list)
Ama bizim su anda ilgilendigimiz konu karakter dizileri oldugu iin derhal konumuza
dnyoruz. dir(str) fonksiyonu dsnda, karakter dizilerini listelemek iin su yntemden de
yararlanabiliriz:
>>> dir("")
Akas benim en ok tercih ettigim yntem de budur. Zira kullanlabilecek yntemler iinde
en pratik ve kolay olan bana buymus gibi geliyor. Burada grdgnz gibi, dir()
fonksiyonuna parametre olarak bos bir karakter dizisi veriyoruz. Biliyorsunuz, Pythonda
karakter dizileri trnak isaretleri yardmyla teki veri tiplerinden ayrlyor. Dolaysyla ii bos
dahi olsa, yan yana gelmis iki adet trnak isareti, bir karakter dizisi olusturmak iin geerli ve
yeterli sart yerine getirmis oluyor. Isterseniz bunu bir de type() fonksiyonunu kullanarak test
edelim (Bu fonksiyonu nceki yazlarmzdan hatrlyor olmalsnz):
>>> a = ""
>>> type(a)
<type 'str'>
Dedigim gibi, fonksiyon iinde dogrudan bir karakter dizisi vermenin bir anlam yoktur. Ama
Python yine de sizi krmayacak ve teki yntemler yardmyla da elde edebileceginiz su
kty ekrana dkecektir:
['__add__', '__class__', '__contains__', '__delattr__',
'__doc__', '__eq__', '__ge__', '__getattribute__',
'__getitem__', '__getnewargs__', '__getslice__',
'__gt__', '__hash__', '__init__', '__le__', '__len__',
124
Grdgnz gibi, Pythonda karakter dizilerinin bir hayli metodu var. Eger bu listeleme
biimi gznze biraz karsk grndyse, elbette kty istediginiz gibi biimlendirmek sizin
elinizde.
Mesela nceki bilgilerinizi de kullanp syle bir sey yaparak kty biraz daha okunakl hale
getirebilirsiniz:
>>> for i in dir(""):
...
print i
Hatta ka adet metot oldugunu da merak ediyorsanz syle bir yol izleyebilirsiniz. (Elle tek
tek sayarm, diyenlere teessflerimi iletiyorum.)
>>> print len(dir(""))
Simdi
sra geldi bu metotlar tek tek incelemeye. Yalnz ncelikle sunu syleyelim: Bu
blmde __xxx__ seklinde listelenmis metotlar incelemeyecegiz. Karakter dizisi metotlar
dendigi zaman temel olarak anlaslmas gereken sey, dir() fonksiyonu ile listelenen metotlar
arasnda __xxx__ seklinde GSTERILMEYEN metotlardr. __xxx__ seklinde
gsterilenler zel metotlar olarak adlandrlyorlar ve bunlarn, bu yaznn kapsamna
girmeyen, farkl kullanm alanlar var.
Bunu da syledikten sonra artk asl konumuza dnebiliriz.
Not: Asagdaki metotlar Trke karakter ieren karakter dizileri ile birlikte kullanmaya
alstgnzda beklediginiz sonular alamadgnz grebilirsiniz. Bu metotlarn Trke
karakterler ile birlikte nasl kullanlmas gerektigi blm sonunda aklanacaktr.
Ya da degiskenler yardmyla:
125
>>> a = adana
>>> a.capitalize()
Adana
Yalnz dikkat etmemiz gereken bir nokta var: Bu metot yardmyla birden fazla kelime ieren
karakter dizilerinin sadece ilk kelimesinin ilk harfini bytebiliyoruz:
>>> a = "parolanz giriniz"
>>> a.capitalize()
kullandgmzda o harf klyor; eger bu harf o anda kkse, bu metot o harfi byk harfe
eviriyor. Grdgnz gibi, bu metodun ne yaptgn, anlatarak aklamak zor oluyor. O
yzden hemen birka rnek yapalm:
>>> a = "kebap"
>>> a.swapcase()
KEBAP
>>> b = "KEBAP"
>>> b.swapcase()
kebap
>>> c = "KeBaP"
>>> c.swapcase()
kEbAp
Grdgnz gibi, parantez iinde belirttigimiz say braklacak bosluktan ziyade, bir karakter
dizisinin ne kadar yer kaplayacagn gsteriyor. Yani mesela yukardaki rnegi gz nne
alrsak, asl karakter dizisi (a) + 2 adet # isareti = 3 adet karakter dizisinin yerlestirildigini
9.6. title metodu
127
gryoruz. Eger karakter dizimiz, tek harf yerine harften olussayd, parantez iinde
verdigimiz says hi bir ise yaramayacakt. Byle bir durumda, # isaretini ktda
gsterebilmek iin parantez iinde en az 4 saysn kullanmamz gerekirdi.
'
128
print str(i).zfill(2)
while i > 20:
continue
Grdgnz gibi, replace() metodu yardmyla karakter dizisi iindeki btn a harflerini
kaldrp yerlerine o harfini koyduk. Burada normalde print() deyimini kullanmasak da olur,
ama karakter dizisi iinde Trkeye zg harfler oldugu iin, eger print() deyimini
kullanmazsak ktda bu harfler bozuk grnecektir.
Bu metodu, isterseniz bir karakteri silmek iin de kullanabilirsiniz. O zaman syle bir sey
yapmamz gerekir:
>>> karakter = "Adanal istihza"
>>> karakter_dgs = karakter.replace("a","")
>>> print karakter_dgs
Adnl istihz
Burada bir karakteri silmek iin ii bos bir karakter dizisi olusturdugumuza dikkat edin.
replace() metodunun, yukardaki formlde belirtmedigimiz nc bir parametresi daha
vardr. Dikkat ettiyseniz, yukardaki kod rneklerinde replace metodu karakter dizisi iindeki
bir karakteri, dizi iinde getigi her yerde degistiriyordu. Yani rnegin a.replace(b,c)
dedigimizde, a degiskeninin sakladg karakter dizisi iinde ne kadar b harfi varsa
bunlarn hepsi cye dnsyor. Bahsettigimiz nc parametre yardmyla, karakter dizisi
iinde geen harflerin ka tanesinin degistirilecegini belirleyebiliyoruz:
>>> karakter = "Adanal istihza"
>>> karakter_dgs = karakter.replace("a","",2)
>>> print karakter_dgs
Adnl istihza
129
Burada, Adanal istihza karakter dizisi iinde geen a harflerinden 2 tanesini siliyoruz.
a harfi ile A harfinin Pythonun gznde birbirlerinden farkl iki karakterler oldugunu
unutmayn...
Grldg gibi eger bir karakter dizisi parantez iinde belirtilen harf veya karakterle
baslyorsa, yani bir karakter dizisinin ilk harfi veya karakteri parantez iinde belirtilen harf
veya karakterse dogru anlamna gelen True ktsn; aksi halde ise yanls anlamna
gelen False ktsn elde ediyoruz.
Bu metot sayesinde karakter dizilerini ilk harflerine gre sorgulayp sonuca gre istedigimiz
islemleri yaptrabiliyoruz:
>>> liste = ["elma", "erik", "ev", "elbise",
... "karpuz", "armut", "kebap"]
>>> for i in liste:
...
if i.startswith("e"):
...
i.replace("e", "i")
...
'ilma'
'irik'
'iv'
'ilbisi'
130
>>> a = "elma"
>>> a.endswith("a")
True
>>> b = "armut"
>>> a.endswith("a")
False
Demek ki Sinan Pasa Pasaj karakter dizisi iinde 5 adet a harfi varms...
Ama:
131
>>> b = "k3zb6n"
>>> b.isalpha()
False
132
Eger denetleme sonucunda True alyorsak, o karakter dizisi alfanmeriktir. Bir de suna
bakalm:
>>> b = "123abc>"
>>> b.isalnum()
False
133
Grdgnz gibi, eger karakter dizisinin ilk harfleri bykse bu metot True kts; aksi
halde False kts veriyor.
Son rnekten de grdgmz gibi, bu metodun True kts verebilmesi iin karakter dizisi
iinde en az bir adet bosluk karakteri olmas gerekiyor.
134
Bu metot karakter dizilerini soldan saga dogru okur. Dolaysyla eger aradgmz karakter
birden fazla sayda bulunuyorsa, ktda yalnzca en soldaki karakter grnecektir:
>>> b = "adana"
>>> a.find("a")
0
find() metodu bize ayn zamanda bir karakter dizisinin belli noktalarnda arama yapma imkan
da sunar. Bunun iin syle bir szdizimini kullanabiliriz:
"karakter_dizisi".find("aranacak_karakter", ba
slang_noktas, biti
s_noktas)
135
Dogal olarak find() metodu karakter dizisi iinde ilk buldugu a harfinin konumunu
syleyecektir. Bizim rnegimizde a harfi kelimenin basnda getigi iin ktda 0 ifadesini
gryoruz. Demek ki bu karakter dizisi iinedeki ilk a harfi 0nc konumdayms.
Istersek syle bir arama yntemi de kullanabiliriz:
>>> a.find("a", 1, 3)
Bununla ilgili kendi kendinize baz denemeler yaparak, isleyisi tam anlamyla
kavrayabilirsiniz.
Grdgnz gibi, rfind() metodu karakter dizisini sagdan sola dogru okudugu iin ncelikle
en sondaki a harfini dndrd.
136
Bu metot da bize, tpk find() metodunda oldugu gibi, konuma gre arama olanag sunar:
>>> b = "kahramanmara
s"
>>> b.index("a", 8, 10)
9
Simdi
137
>>> ".".join(a)
Sanrm burada join() metodunun ne is yaptgn anladnz. Linux karakter dizisi iindeki
btn karakterlerin arasna birer tane . (nokta) koydu. Tabii ki, nokta yerine baska
karakterler de kullanabiliriz:
>>> "*".join(a)
L*i*n*u*x
Dikkat ederseniz join() metodunun szdizimi teki metotlarnkinden biraz farkl. join()
metodunda parantez iine dogrudan degiskenin kendisi yazdk. Yani a.join(*) gibi bir sey
yazmyoruz. Bu metot yardmyla ayrca listeleri de etkili bir biimde karakter dizisine
evirebiliriz. Mesela elimizde syle bir liste olsun:
>>> a = ["python", "php", "perl", "C++", "Java"]
Bu listenin gelerini karakter dizileri halinde ve belli bir lte gre sralamak iin su kodu
kullanyoruz:
>>> "; ".join(a)
python; php; perl; C++; Java
138
Elimizdeki ipucuna gre sifreli mesajdaki t harfinin karslg p olacak. Alfabetik olarak
dsnrsek:
1. t harfi, p harfine gre, 5 harf geride kalyor (p, r, s, s, t)
2. s harfi o harfine gre 5 harf geride kalyor (o, , p, r, s)
3. j harfi m harfine gre 4 harf geride kalyor (j, k, l, m)
Bu karmn bizi bir yere gtrmeyecegi ak. nk harfler arasnda ortak bir iliski
bulamadk. Peki ya alfabedeki Trke karakterleri yok sayarsak? Bir de yle deneyelim:
1. t harfi, p harfine gre, 4 harf geride kalyor (p, r, s, t)
2. s harfi o harfine gre 4 harf geride kalyor (o, p, r, s)
3. j harfi m harfine gre 4 harf geride kalyor (j, k, l, m)
Bylece karakterler arasndaki iliskiyi tespit etmis olduk. Simdi
Sifreli
Burada kaynak, sifreli metnin yapsn; hedef ise alfabenin normal yapsn temsil ediyor.
kaynak adl degiskende d harfinden baslamamzn nedeni yukarda kesfettigimiz
harfler-aras iliskidir. Dikkat ederseniz, hedefteki harfleri, kaynaktaki harflere gre, her
bir harf drt sra geride kalacak sekilde yazdk. (d -> a, e ->b, gibi...) Dikkat edecegimiz bir
baska nokta ise bunlar yazarken Trke karakter kullanmamamz gerektigidir:
cevir = string.maketrans(kaynak,hedef)
Burada ise, yukarda tanmladgmz harf kmeleri arasnda bir evrim islemi baslatabilmek
iin string modlnn maketrans() adl fonksiyonundan yararlanyoruz. Bu komut, parantez
9.28. translate metodu
139
iinde gsterdigimiz kaynak degiskenini hedef degiskenine eviriyor; aslnda bu iki harf
kmesi arasnda bir iliski kuruyor. Bu islem sonucunda kaynak ve hedef degiskenleri
arasndaki iliskiyi gsteren bir forml elde etmis olacagz:
soncevir = metin.translate(cevir)
Bu komut yardmyla, yukarda cevir olarak belirledigimiz forml, metin adl karakter
dizisine uyguluyoruz:
print soncevir
140
Grdgnz gibi, partition() metodu karakter dizisini ilk i harfinden bld. Simdi
ayn
islemi rpartition() metodu ile yapalm:
>>> b.rpartition("i")
('ist', 'i', 'hza')
rpartition() metodu ise, karakter dizisini sagdan sola dogru okudugu iin ilk i harfinden
degil, son i harfinden bld karakter dizisini...
partition() ve rpartition() metotlar, ltn karakter dizisi iinde bulunmadg durumlarda da
farkl tepkiler verir:
>>> b.partition("g")
('istihza', '', '')
>>> b.rpartition("g")
('', '', 'istihza')
Grdgnz gibi, partition() metodu bos karakter dizilerini saga dogru yaslarken, rpartition()
metodu sola dogru yaslad.
141
sralayabiliyorduk:
>>> a = ["Debian", "Pardus", "Ubuntu", "SuSe"]
>>> b = ", ".join(a)
>>> print b
Debian, Pardus, Ubuntu, SuSe
Bylece her karakter dizisi farkl bir liste gesi haline geldi:
>>> yeni[0]
'Debian'
>>> yeni[1]
'Pardus'
>>> yeni[2]
'Ubuntu'
>>> yeni[3]
'SuSe'
Bu metotta ayrca isterseniz ltn yansra ikinci bir parametre daha kullanabilirsiniz:
>>> c = b.split(",", 1)
>>> print c
['Debian', ' Pardus, Ubuntu, SuSe']
Grdgnz gibi, parantez iinde , ltnn yanna bir adet 1 says koyduk. kty
dikkatle inceledigimizde split() metodunun bu parametre yardmyla karakter dizisi iinde
sadece bir adet blme islemi yaptgn gryoruz. Yani olusan listenin bir gesi Debian,
teki gesi de Pardus, Ubuntu, SuSe oldu. Bunu su sekilde daha ak grebiliriz:
>>> c[0]
'Debian'
>>> c[1]
' Pardus, Ubuntu, SuSe'
143
Grdgnz gibi listenin 0. gesi Debianken; listenin 1. gesi Pardus, Ubuntu, Suse
ls. Yani bu l tek bir karakter dizisi seklinde tanmlanms.
Yukarda tanmladgmz yeni adl listeyle c adl listenin uzunluklarn karslastrarak
durumu daha net grebiliriz:
>>> len(yeni)
4
>>> len(c)
2
Bu rnekte ikisi arasndaki fark pek belli olmasa da, split() metodu soldan saga dogru
okurken, rsplit() metodu sagdan sola dogru okuyor. Daha ak bir rnek verelim:
>>> orneksplit = a.split(".", 1)
>>> print orneksplit
['www', 'python.quotaless.com']
>>> ornekrsplit = a.rsplit(".", 1)
>>> print ornekrsplit
['www.python.quotaless', 'com']
Sanrm bu sekilde ikisi arasndaki fark daha belirgin oldu. yle degil diyorsanz bir de suna
bakn:
144
>>> orneksplit[0]
'www'
>>> ornekrsplit[0]
'www.python.quotaless'
Bylece Karakter Dizisi Metotlarn bitirmis olduk. Sra geldi, bu metotlarn Trke
karakterler ile olan uyumsuzluklarn ve bu sorunu nasl zecegimizi anlatmaya...
Grdgnz gibi, sekerli ay karakter dizisinin ilk harfi olan sde herhangi bir degisiklik
olmad. Halbuki capitalize() metodunun bu harfi bytmesi gerekiyordu. Bu problemi su
sekilde asabiliriz:
>>> a = u"
sekerli ay"
>>> print a.capitalize()
Sekerli ay
Burada sekerli ay karakter dizisini bir unicode karakter dizisi olarak tanmladk. Gelin
isterseniz bunu dogrulayalm:
>>> a = "
sekerli ay"
>>> type(a)
<type str>
Karakter dizisini normal bir sekilde tanmladgmzda type(a) sorgusu <type str> degerini
veriyor.
Bir de suna bakalm:
>>> a = u"
sekerli ay"
>>> type(a)
<type 'unicode'>
145
Karakter dizisinin ds tarafna bir adet u harfi ekledigimizde ise normal karakter dizilerinden
farkl bir veri tipi olan unicode karakter dizisi elde etmis oluyoruz.
Bylece capitalize() metodu bu karakter dizisinin ilk harfini dogru bir sekilde bytebildi.
Not: Unicode konusunu birka blm sonra ayrntl olarak ele alacagz.
Ayn sorun teki metotlar iin de geerlidir:
>>> a = "
sekerli ay"
AY" vermeli.
>>> print a.upper() #"
SEKERLI
sEKERLI AY
>>> a = "
sEkErLi Ay"
aY" vermeli.
>>> print a.swapcase() #"
SeKeRlI
seKeRlI aY
>>> a = "
SEKERL
I AY"
>>> print a.lower() #"
sekerli ay" vermeli.
Sekerl
I ay
Ancak karakter dizisini unicode olarak tanmlamann dahi ise yaramayacag bir durum da
vardr. Trkedeki i harfi hibir dnsmde I sonucunu vermez... rnegin:
>>> a = u"
sekerli ay"
>>> print a.upper()
SEKERLI AY
>>> a = "
sEkErLi Ay"
>>> print a.swapcase()
SeKeRlI aY
146
Grdgnz gibi, i harfinin byk hali yanls bir sekilde I oluyor. Ayn biimde I harfi
de kltldgnde harfini degil, i harfini verecektir:
>>> a = u"ISLIK"
>>> print a.lower()
islik
Bu sorunlar zebilmek iin, kendi metodunuzu icat etmeyi deneyebilirsiniz. Mesela syle
bir sey yazabilirsiniz:
# -*- coding: utf-8 -*donusturme_tablosu = {u'i':
u'
I':
u'':
u'I':
u'
I',
u'i',
u'I',
u''}
def duzelt(kardiz):
s = ''
for i in kardiz:
s += donusturme_tablosu.get(i, i)
return s
Burada get() metodunu kullanarak, kardiz iindeki her bir karakteri donusturme_tablosu
iinde aryoruz. Eger kardiz iinde mesela i harfi varsa, bunu szlkteki karslg olan I
harfine dnstrp s adl degiskene gnderiyoruz. rnegin kitap gibi bir kelime, s
degiskenine su sekilde gnderilecektir:
k
Itap
147
print duzelt(u"
sekerli ay").title()
print duzelt(u"SICAK AY").lower()
Grdgnz gibi, karakter dizisini nce duzelt() fonksiyonuna gnderip iindeki Trke
karakterleri dzgn bir sekilde dnstryoruz, ardndan da bu dzeltilmis karakter dizisini
ilgili karakter dizisi metoduna gnderiyoruz.
Yukardaki metot swapcase() hari btn karakter dizisi metotlarndaki Trke problemini
zer. swapcase() metodu iin ise syle bir fonksiyon tanmlayabiliriz:
def tr_swapcase(kardiz):
s = ''
for i in kardiz:
if i.isupper():
s += duzelt(i).lower()
else:
s += duzelt(i).upper()
return s
Bylece Pythondaki hemen hemen btn karakter dizisi metotlarn inceledik. Ama dikkat
ederseniz metot listesi iindeki metodu anlatmadk. Bunlar, encode, decode ve format
metotlar... Bunlar daha sonraki konularda anlatmak zere simdilik bir kenara brakyoruz.
Bu konuyu iyice sindirebilmek iin kendi kendinize bolca rnek ve denemeler yapmanz, bu
konuyu arada srada tekrar etmenizi neririm.
148
BLM 10
Dzenli ifadeler Python Programlama Dilindeki en etrefilli konulardan biridir. Hatta dzenli
ifadelerin Python iinde ayr bir dil olarak dsnlmesi gerektigini syleyenler dahi vardr.
Btn zorluklarna ragmen programlama deneyimimizin bir noktasnda mutlaka karsmza
kacak olan bu yapy grenmemizde byk fayda var. Dzenli ifadeleri grendikten sonra,
elle yaplmas saatler srecek bir islemi saliseler iinde yapabildiginizi grdgnzde eminim
dzenli ifadelerin ne byk bir nimet oldugunu anlayacaksnz. Tabii her gzel sey gibi,
dzenli ifadelerin nimetlerinden yararlanabilecek dzeye gelmek de biraz kan ve gzyas
istiyor.
Peki, dzenli ifadeleri kullanarak neler yapabiliriz? ok genel bir ifadeyle, bu yapy
kullanarak metinleri veya karakter dizilerini parmagmzda oynatabiliriz. rnegin bir web
sitesinde dagnk halde duran verileri bir rpda ayklayabiliriz. Bu veriler, mesela, toplu
halde grmek istedigimiz web adreslerinin bir listesi olabilir. Bunun dsnda, rnegin, ok
sayda belge zerinde tek hareketle istedigimiz degisiklikleri yapabiliriz.
Genel bir kural olarak, dzenli ifadelerden kaabildigimiz mddete kamamz gerekir. Eger
Pythondaki karakter dizisi metotlar, o anda yapmak istedigimiz sey iin yeterli geliyorsa
mutlaka o metotlar kullanmalyz. nk karakter dizisi metotlar, dzenli ifadelere kyasla
hem daha basit, hem de ok daha hzldr. Ama bir noktadan sonra karakter dizilerini
kullanarak yazdgnz kodlar iyice karmasklasmaya baslamssa, kodlarn her taraf if
deyimleriyle dolmussa, hatta basit bir islemi gereklestirmek iin yazdgnz kod sayfa
snrlarn zorlamaya baslamssa, iste o noktada artk dzenli ifadelerin dnyasna adm
atmanz gerekiyor olabilir. Ama bu durumda Jamie Zawinskinin su szn de aklnzdan
karmayn: Bazlar, bir sorunla kars karsya kaldklarnda syle der: Evet, dzenli
ifadeleri kullanmam gerekiyor. Iste onlarn bir sorunu daha vardr artk...
Basta da syledigim gibi, dzenli ifadeler bize zorluklar unutturacak kadar byk kolaylklar
sunar. Emin olun yzlerce dosya zerinde tek tek elle degisiklik yapmaktan daha zor degildir
dzenli ifadeleri grenip kullanmak... Hem zaten biz de bu sayfalarda bu sevimsiz konuyu
olabildigince sevimli hale getirmek iin elimizden gelen abay gsterecegiz. Sizin de aba
gstermeniz, bol bol alstrma yapmanz durumunda dzenli ifadeleri kavramak o kadar da
zorlayc olmayacaktr. Unutmayn, dzenli ifadeler ne kadar ugrastrc olsa da programcnn
en nemli silahlarndan biridir. Hatta dzenli ifadeleri grendikten sonra onsuz geen
yllarnza acyacaksnz.
Simdi
149
Bir nceki blmde syledigimiz gibi, dzenli ifadeler bir programcnn en nemli
silahlarndan biridir. Su
halde silahmzn zelliklerine bakalm. Yani bu yapnn bize sundugu
aralar syle bir listeleyelim. Etkilesimli kabukta su kodu yazyoruz:
>>> dir(re)
Ne yazk ki, Pythonun yardm dosyalar hep Ingilizce. Dolaysyla eger Ingilizce
bilmiyorsanz, bu yardm dosyalar pek isinize yaramayacaktr. Bu arada yukardaki yardm
blmnden kmak iin klavyedeki q dgmesine basmanz gerekir.
Varsayalm ki biz bu karakter dizisi iinde python kelimesi geip gemedigini grenmek
istiyoruz. Ve bunu da dzenli ifadeleri kullanarak yapmak istiyoruz. Dzenli ifadeleri bu
rnege uygulayabilmek iin yapmamz gereken sey, ncelikle bir dzenli ifade kalb
olusturup, daha sonra bu kalb yukardaki karakter dizisi ile karslastrmak. Biz btn bu
islemleri match() metodunu kullanarak yapabiliriz:
150
>>> re.match("python", a)
Burada, python seklinde bir dzenli ifade kalb olusturduk. Dzenli ifade kalplar match()
metodunun ilk argmandr (yani parantez iindeki ilk deger). Ikinci argmanmz ise (yani
parantez iindeki ikinci deger), hazrladgmz kalb kendisiyle eslestirecegimiz karakter
dizisi olacaktr.
Klavyede ENTER tusuna bastktan sonra karsmza syle bir kt gelecek:
<_sre.SRE_Match object at 0xb7d111e0>
Bu kt, dzenli ifade kalbnn karakter dizisi ile eslestigi anlamna geliyor. Yani aradgmz
sey, karakter dizisi iinde bulunmus. Python bize burada ne buldugunu sylemiyor. Bize
syledigi tek sey, aradgmz seyi buldugu... Bunu syleme tarz da yukardaki gibi...
Yukardaki ktda grdgmz ifadeye Pythoncada eslesme nesnesi (match object) ad
veriliyor. nk match() metodu yardmyla yaptgmz sey aslnda bir eslestirme islemidir
(match kelimesi Ingilizcede eslesmek anlamna geliyor). Biz burada python dzenli
ifadesinin a degiskeniyle eslesip eslesmedigine bakyoruz. Yani re.match(python,a)
ifadesi araclgyla python ifadesi ile a degiskeninin tuttugu karakter dizisinin eslesip
eslesmedigini sorguluyoruz. Bizim rnegimizde python a degiskeninin tuttugu karakter
dizisi ile eslestigi iin bize bir eslesme nesnesi dndrlyor. Bir de su rnege bakalm:
>>> re.match("Java", a)
Burada ENTER tusuna bastgmzda hi bir kt almyoruz. Aslnda biz grmesek de Python
burada None kts veriyor. Eger yukardaki komutu syle yazarsak None ktsn biz de
grebiliriz:
>>> print re.match("Java",a)
None
Grdgnz gibi, ENTER tusuna bastktan sonra None kts geldi. Demek ki Java
ifadesi, a degiskeninin tuttugu karakter dizisi ile eslesmiyormus. Buradan kardgmz
sonuca gre, Python match() metodu yardmyla aradgmz seyi eslestirdigi zaman bir
eslesme nesnesi (match object) dndryor. Eger eslesme yoksa, o zaman da None degerini
dndryor.
Biraz kafa karstrmak iin syle bir rnek verelim:
>>> a = "Python gl bir dildir"
>>> re.match("gl", a)
Burada a degiskeninde gl ifadesi getigi halde match() metodu bize bir eslesme
nesnesi dndrmedi. Aslnda bu normal. nk match() metodu bir karakter dizisinin sadece
en basna bakar. Yani Python gl bir dildir ifadesini tutan a degiskenine
re.match(gl,a) gibi bir fonksiyon uyguladgmzda, match() metodu a degiskeninin
yalnzca en basna bakacag iin ve a degiskeninin en basnda gl yerine python
oldugu iin, match() metodu bize olumsuz yant veriyor.
Aslnda match() metodunun yaptg bu isi, karakter dizilerinin split() metodu yardmyla da
yapabiliriz:
10.1. Dzenli Ifadelerin Metotlar
151
Eger dzenli ifadelerden tek beklentiniz bir karakter dizisinin en basndaki veriyle eslestirme
islemi yapmaksa, split() veya startswith() metotlarn kullanmak daha mantkldr. nk
split() ve startswith() metotlar match() metodundan ok daha hzl alsacaktr.
match() metodunu kullanarak bir ka rnek daha yapalm:
>>> sorgu = "1234567890"
>>> re.match("1",sorgu)
<_sre.SRE_Match object at 0xb7d111e0>
>>> re.match("1234",sorgu)
<_sre.SRE_Match object at 0xb7d111e0>
>>> re.match("124",sorgu)
None
metodu ile bulunan seyin ne oldugunu gremiyoruz. Ama istersek tabii ki bulunan seyi de
grme imknmz var. Bunun iin group() metodunu kullanacagz:
>>> a = "perl, python ve ruby yksek seviyeli dillerdir."
>>> b = re.match("perl",a)
>>> print b.group()
perl
Grdgnz gibi, b degiskeninin tipi bir eslesme nesnesi (match object). Isterseniz bu
nesnenin metotlarna bir gz gezdirebiliriz:
>>> dir(b)
Peki, eslestirmek istedigimiz dzenli ifade kalb bulunamazsa ne olur? yle bir durumda
yukardaki kodlar hata verecektir. Hemen bakalm:
stanbul", iddia)
>>> nesne = re.match("I
>>> print nesne.group()
Hata mesajmz:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
Byle bir hata, yazdgnz bir programn kmesine neden olabilir. O yzden kodlarmz suna
benzer bir sekilde yazmamz daha mantkl olacaktr:
>>> nesne = re.match("
Istanbul",iddia)
>>> if nesne:
...
print "e
sle
sen ifade: %s" %nesne.group()
... else:
...
print "e
sle
sme ba
sarsz!"
Simdi
isterseniz bu match() metoduna bir ara verip baska bir metodu inceleyelim.
10.1. Dzenli Ifadelerin Metotlar
153
Yukardaki kod, karakter dizisinin basnda bir eslesme bulamadg iin bize None degeri
dndryordu. Ama eger ayn islemi syle yaparsak, daha farkl bir sonu elde ederiz:
>>> a = "Python gl bir dildir"
>>> re.search("gl", a)
<_sre.SRE_Match object at 0xb7704c98>
Simdiye
kadar hep karakter dizileri zerinde alstk. Isterseniz biraz da listeler zerinde
rnekler verelim.
Syle
Ne oldu? Hata aldnz, degil mi? Bu normal. nk dzenli ifadeler karakter dizileri zerinde
isler. Bunlar dogrudan listeler zerinde islem yapamaz. O yzden bizim Pythona biraz
yardmc olmamz gerekiyor:
>>> for i in liste::
...
b = re.search("kebap", i)
154
...
...
...
kebap
if b:
print b.group()
Ilerde bilgimiz artnca daha yetkin kodlar yazabilecek duruma gelecegiz. Ama simdilik
elimizde olanlar ancak yukardaki kodu yazmamza msaade ediyor. Unutmayn, dzenli
ifadeler sahasnda snma turlar atyoruz daha...
155
Grdgnz gibi, metinde geen btn Python kelimelerini bir rpda liste olarak aldk.
Ayn islemi search() metodunu kullanarak yapmak istersek yolu biraz uzatmamz gerekir:
>>> liste = metin.split()
>>> for i in liste:
...
nesne = re.search("Python",i)
...
if nesne:
...
print nesne.group()
...
Python
Python
Python
Python
Python
Python
Grdgnz gibi, metinde geen btn Python kelimelerini search() metodunu kullanarak
bulmak iin ncelikle metin adl karakter dizisini, daha nce karakter dizilerini islerken
grdgmz split() metodu yardmyla bir liste haline getiriyoruz. Ardndan bu liste zerinde
bir for dngs kurarak search() ve group() metotlarn kullanarak btn Python
kelimelerini ayklyoruz. Eger karakter dizisini yukardaki sekilde listeye dnstrmezsek
syle bir netice alrz:
>>> nesne = re.search("Python", metin)
>>> print nesne.group()
Python
Bu sekilde metinde geen sadece ilk Python kelimesini alabiliyoruz. Eger, dogrudan
karakter dizisine, listeye dnstrmeksizin, for dngs uygulamaya kalkarsak syle bir sey
olur:
>>> for i in a:
...
nesne = re.search("Python",metin)
156
...
...
if nesne:
print nesne.group()
Grdgnz gibi, yukardaki kod ekranmz Python ktsyla dolduruyor. Eger en sonda
print nesne.group() yazmak yerine print i yazarsanz, Pythonun ne yapmaya alstgn ve
neden byle bir kt verdigini anlayabilirsiniz.
10.2 Metakarakterler
Simdiye
kadar dzenli ifadelerle ilgili olarak verdigimiz rnekler sizi biraz sasrtms olabilir.
Zor dedigin bunlar myd? diye dsnms olabilirsiniz. Haklsnz, zira zor dedigim,
buraya kadar olan ksmda verdigim rneklerden ibaret degildir. Buraya kadar olan blmde
verdigim rnekler isin en temel ksmn gzler nne sermek iindi. Simdiye
kadar olan
blmde, mesela, python karakter dizisiyle eslestirme yapmak iin python kelimesini
kullandk. Esasnda bu, dzenli ifadelerin en temel zelligidir. Yani python karakter dizisini
bir dzenli ifade sayacak olursak (ki zaten yledir), bu dzenli ifade en basta kendisiyle
eslesecektir. Bu ne demek? Syle
Diyelim ki, biz bu liste iinden zcan, zkan ve zhan gelerini ayklamak/almak
istiyoruz. Bunu yapabilmek iin yeni bir bilgiye ihtiyacmz var: Metakarakterler.
Metakarakterler; kabaca, programlama dilleri iin zel anlam ifade eden sembollerdir.
rnegin daha nce grdgmz \n bir bakma bir metakarakterdir. nk \n sembol
Python iin zel bir anlam tasr. Python bu sembol grdg yerde yeni bir satra geer.
Yukarda kendisiyle eslesmeyen karakterler ifadesiyle kastettigimiz sey de iste bu
metakarakterlerdir. rnegin, a harfi yalnzca kendisiyle eslesir. Tpk istihza kelimesinin
yalnzca kendisiyle eslesecegi gibi... Ama mesela \t ifadesi kendisiyle eslesmez. Python bu
isareti grdg yerde sekme (tab) dgmesine baslms gibi tepki verecektir. Iste dzenli
ifadelerde de buna benzer metakarakterlerden yararlanacagz. Dzenli ifadeler iinde de, zel
anlam ifade eden pek ok sembol, yani metakarakter vardr. Bu metakarakterlerden biri de [
] semboldr. Simdi
Bu kodu byle yazmamamz gerektigini artk biliyoruz. Aksi halde hata alrz. nk daha
nce de dedigimiz gibi, dzenli ifadeler karakter dizileri zerinde islem yapabilir. Listeler
zerinde degil. Dolaysyla komutumuzu su sekilde vermemiz gerekiyor:
10.2. Metakarakterler
157
Ancak, bu rnekte pek belli olmasa da, son yazdgmz kod her zaman istedigimiz sonucu
vermez. Mesela listemiz syle olsayd:
>>> liste = ["zcan demir", "mehmet", "sleyman",
... "selim", "kemal", "zkan nuri", "esra", "dndar",
... "esin", "esma", "zhan kamil", "zlem"]
Yukardaki kod bu liste zerine uygulandgnda, sadece almak istedigimiz ksm degil, ilgisiz
ksmlar da gelecektir.
Grdgnz gibi, uygun kodlar kullanarak, zcan, zkan ve zhan gelerini listeden
kolayca aykladk. Bize bu imkn veren sey ise [ ] adl metakarakter oldu. Aslnda [ ]
metakarakterinin ne ise yaradgn az ok anlams olmalsnz. Ama biz yine de syle bir
bakalm bu metakaraktere:
[ ] adl metakarakter, yukarda verdigimiz listedeki z ile baslayp, c, h veya k
harflerinden herhangi biri ile devam eden ve an ile biten btn geleri ayklyor. Gelin
bununla ilgili bir rnek daha yapalm:
>>> for i in liste:
...
nesne = re.search("es[mr]a",i)
...
if nesne:
...
print nesne.group()
Grdgnz gibi, es ile baslayp, m veya r harflerinden herhangi biriyle devam eden ve
sonunda da a harfi bulunan btn geleri aykladk. Bu da bize esma ve esra ktlarn
verdi...
Dedigimiz gibi, metakarakterler programlama dilleri iin zel anlam ifade eden sembollerdir.
Normal karakterlerden farkl olarak, metakarakterlerle karslasan bir bilgisayar normalden
farkl bir tepki verecektir. Yukarda metakarakterlere rnek olarak \n ve \t kas dizilerini
vermistik. rnegin Pythonda print \n gibi bir komut verdigimizde, Python ekrana \n
yazdrmak yerine bir alt satra geecektir. nk \n Python iin zel bir anlam tasmaktadr.
Dzenli ifadelerde de birtakm metakarakterlerin kullanldgn grendik. Bu metakarakterler,
dzenli ifadeleri dzenli ifade yapan seydir. Bunlar olmadan dzenli ifadelerle yararl bir is
yapmak mmkn olmaz. Bu giris blmnde dzenli ifadelerde kullanlan metakarakterlere
rnek olarak [ ] semboln verdik. Herhangi bir dzenli ifade iinde [ ] semboln gren
Python, dogrudan dogruya bu sembolle eslesen bir karakter dizisi aramak yerine, zel bir
islem gereklestirecektir. Yani [ ] sembol kendisiyle eslesmeyecektir...
Pythonda bulunan temel metakarakterleri topluca grelim:
158
[ ] . \* + ? { } ^ $ | ( )
10.2.1 [ ] (Kseli
Parantez)
[ ] adl metakaraktere nceki blmde deginmistik. Orada verdigimiz rnek suydu:
>>> for i in liste:
...
nesne = re.search("z[chk]an", i)
...
if nesne:
...
print nesne.group()
Yukardaki rnekte, bir liste iinde geen zcan, zhan ve zkan gelerini ayklyoruz.
Burada bu gedeki farkl karakterleri (c, h ve k) kseli parantez iinde nasl
belirttigimize dikkat edin. Python, kseli parantez iinde grdg btn karakterleri tek tek
liste gelerine uyguluyor. nce z ile baslayan btn geleri alyor, ardndan z
hecesinden sonra c harfiyle devam eden ve an hecesi ile biten geyi buluyor. Bylece
zcan gesini bulmus oldu. Ayn islemi, z hecesinden sonra h harfini barndran ve
an hecesiyle biten geye uyguluyor. Bu sekilde ise zhan gesini bulmus oldu. En son
hedef ise z ile baslayp k harfi ile devam eden ve an ile biten ge. Yani listedeki
zkan gesi... En nihayetinde de elimizde zcan, zhan ve zkan geleri kalms
oluyor.
Bir nceki blmde yine [ ] metakarakteriyle ilgili olarak su rnegi de vermistik:
>>> for i in liste:
...
nesne = re.search("es[mr]a",i)
...
if nesne:
...
print nesne.group()
Bu rnegin de zcan, zkan, zhan rneginden bir fark yok. Burada da Python kseli
parantez iinde grdg btn karakterleri tek tek liste gelerine uygulayp, esma ve esra
gelerini bize veriyor.
Simdi
su kodlar
dikkatlice inceleyin:
10.2. Metakarakterler
159
>>> for i in a:
...
if re.match("[0-9]",i):
...
print i
...
23BH56
4Y7UZ
34534
Burada parantez iinde kullandgmz ifadeye dikkat edin. 0 ile 9 arasndaki btn geleri
ieren bir karakter dizisi tanmladk. Yani ksaca, iinde herhangi bir say barndran geleri
kapsama alanmza aldk. Burada ayrca search() yerine match() metodunu kullandgmza da
dikkat edin. match() metodunu kullanmamzn nedeni, bu metodun bir karakter dizisinin
sadece en basna bakmas... Amacmz say ile baslayan btn geleri ayklamak olduguna
gre, yukarda yazdgmz kod, liste geleri iinde yer alan ve say ile baslayan btn geleri
ayklayacaktr. Biz burada Pythona su emri vermis oluyoruz:
Bana say ile baslayan btn geleri bul! nemli olan bu gelerin sayyla baslamasdr!
Sayyla baslayan bu geler ister harfle devam etsin, ister baska bir karakterle... Sen yeter ki
bana say ile baslayan geleri bul!
Bu emri alan Python, hemen liste gelerini gzden geirecek ve bize 23BH56, 4Y7UZ ve
34534 gelerini verecektir. Dikkat ederseniz, Python bize listedeki TY76Z ve TYUDZ
gelerini vermedi. nk TY76Z iinde saylar olsa da bunlar bizim ltmze uyacak
sekilde en basta yer almyor. TYUDZ gesinde ise tek bir say bile yok...
Simdi
Burada dikkat ederseniz dzenli ifademizin basnda A-Z diye bir sey yazdk. Bu ifade A
ile Z harfleri arasndaki btn karakterleri temsil ediyor. Biz burada yalnzca byk harfleri
sorguladk. Eger kk harfleri sorgulamak isteseydik A-Z yerine a-z diyecektik. Dzenli
ifademiz iinde geen birinci A-Z ifadesi aradgmz karakter dizisi olan TY76Z iindeki
T harfini, ikinci A-Z ifadesi Y harfini, 0-9 ifadesi ise 7 saysn temsil ediyor.
Karakter dizisi iindeki geri kalan harfler ve saylar otomatik olarak eslestirilecektir. O yzden
onlar iin ayr bir sey yazmaya gerek yok. Yalnz bu syledigimiz son sey sizi aldatmasn. Bu
otomatik eslestirme islemi bizim su anda kars karsya oldugumuz karakter dizisi iin
geerlidir. Farkl nitelikteki karakter dizilerinin sz konusu oldugu baska durumlarda isler
byle yrmeyebilir. Dzenli ifadeleri basarl bir sekilde kullanabilmenin ilk sart, zerinde
islem yaplacak karakter dizisini tanmaktr. Bizim rnegimizde yukardaki gibi bir dzenli
ifade kalb olusturmak isimizi gryor. Ama baska durumlarda, duruma uygun baska kalplar
yazmak gerekebilir/gerekecektir. Dolaysyla, tek bir dzenli ifade kalbyla hayatn
gemeyecegini unutmamalyz.
Simdi
10.2.2 . (Nokta)
Bir nceki blmde [] adl metakarakteri incelemistik. Bu blmde ise farkl bir
metakarakteri inceleyecegiz. Inceleyecegimiz metakarakter: .
Bu metakarakter, yeni satr karakteri hari btn karakterleri temsil etmek iin kullanlr.
Mesela:
>>> for i in liste:
...
nesne = re.match("es.a",i)
...
if nesne:
...
print nesne.group()
...
esma
esra
Grdgnz gibi, daha nce [] metakarakterini kullanarak yazdgmz bir dzenli ifadeyi bu
kez farkl sekilde yazyoruz. Unutmayn, bir dzenli ifade birka farkl sekilde yazlabilir. Biz
bunlar iinde en basit ve en anlaslr olann semeliyiz. Ayrca yukardaki kodu birka farkl
sekilde de yazabilirsiniz. Mesela su yazm da bizim durumumuzda geerli bir seenek
olacaktr:
>>> for i in liste:
...
if re.match("es.a",i):
...
print i
Tabii ki biz, o anda zmek durumunda oldugumuz soruna en uygun olan seenegi tercih
etmeliyiz...
Yalnz, unutmamamz gereken sey, bu . adl metakarakterin sadece tek bir karakterin yerini
tutuyor olmasdr. Yani syle bir kullanm bize istedigimiz sonucu vermez:
>>> liste = ["ahmet","kemal", "kamil", "mehmet"]
>>> for i in liste:
...
if re.match(".met",i):
...
print i
10.2. Metakarakterler
161
Simdi
10.2.3 * (Yldz)
Bu metakarakter, kendinden nce gelen bir dzenli ifade kalbn sfr veya daha fazla sayda
eslestirir. Tanm biraz karsk olsa da rnek yardmyla bunu da anlayacagz:
>>> yeniliste = ["st", "sat", "saat", "saaat", "falanca"]
>>> for i in yeniliste:
...
if re.match("sa*t",i):
...
print i
Burada * sembol kendinden nce gelen a karakterini sfr veya daha fazla sayda
eslestiriyor. Yani mesela st iinde sfr adet a karakteri var. Dolaysyla bu karakter
yazdgmz dzenli ifadeyle eslesiyor. sat iinde bir adet a karakteri var. Dolaysyla bu da
eslesiyor. saat ve saaat karakter dizilerinde srasyla iki ve adet a karakteri var. Tabii
ki bunlar da yazdgmz dzenli ifadeyle eslesiyor. Listemizin en son gesi olan falancada da
ilk hecede bir adet a karakteri var. Ama bu gedeki sorun, bunun s harfiyle baslamamas.
nk biz yazdgmz dzenli ifadede, aradgmz seyin s harfi ile baslamasn, sfr veya
daha fazla sayda a karakteri ile devam etmesini ve ardndan da t harfinin gelmesini
istemistik. falanca gesi bu kosullar karslamadg iin szgecimizin dsnda kald.
Burada dikkat edecegimiz nokta, * metakarakterinin kendinden nce gelen yalnzca bir
karakterle ilgileniyor olmas... Yani bizim rnegimizde * sembol sadece a harfinin sfr
veya daha fazla sayda bulunup bulunmamasyla ilgileniyor. Bu ilgi, en bastaki s harfini
kapsamyor. s harfinin de sfr veya daha fazla sayda eslesmesini istersek dzenli ifademizi
s*a*t veya [sa]*t biiminde yazmamz gerekir... Bu iki seenek iinde [sa]*t seklindeki
162
yazm tercih etmenizi tavsiye ederim. Burada, daha nce grendigimiz [ ] metakarakteri
yardmyla sa harflerini nasl grupladgmza dikkat edin...
Simdi
Ama artk elimizde * gibi bir ara olduguna gre simdi istedigimiz seyi yapabiliriz.
Yapmamz gereken tek sey . sembolnden sonra * semboln getirmek:
>>> for i in liste:
...
if re.match(".*met", i):
...
print i
Grdgnz gibi ahmet ve mehmet gelerini bu kez basaryla aykladk. Bunu yapmamz
saglayan sey de * adl metakarakter oldu... Burada Pythona su emri verdik: Bana kelime
basnda herhangi bir karakteri (. sembol herhangi bir karakterin yerini tutuyor) sfr veya
daha fazla sayda ieren ve sonu da met ile biten btn geleri ver!
Bir nceki rnegimizde a harfinin sfr veya daha fazla sayda bulunup bulunmamasyla
ilgilenmistik. Bu son rnegimizde ise herhangi bir harfin/karakterin sfr veya daha fazla
sayda bulunup bulunmamasyla ilgilendik. Dolaysyla .*met seklinde yazdgmz dzenli
ifade, ahmet, mehmet, muhammet, ismet, ksmet ve hatta tek basna met gibi
btn geleri kapsayacaktr. Ksaca ifade etmek gerekirse, sonu met ile biten her sey (met
ifadesinin kendisi de dhil olmak zere) kapsama alanmza girecektir. Bunu gnlk hayatta
nerede kullanabileceginizi hemen anlams olmalsnz. Mesela bir dizin iindeki btn mp3
dosyalarn bu dzenli ifade yardmyla listeleyebiliriz:
>>>
>>>
>>>
>>>
...
...
import os
import re
dizin = os.listdir(os.getcwd())
for i in dizin:
if re.match(".*mp3",i):
print i
Bu rnekte Python bize kt olarak None degerini vermisti. Yani herhangi bir eslesme
bulamamst. nk dedigimiz gibi, match() metodu bir karakter dizisinin yalnzca en basna
bakar. Ama geldigimiz su noktada artk bu kstlamay nasl kaldracagnz biliyorsunuz:
10.2. Metakarakterler
163
>>> re.match(".*gl", a)
Ama match() metodunu bu sekilde zorlamak yerine performans asndan en dogru yol bu tr
isler iin search() metodunu kullanmak olacaktr.
Bunu da getigimize gre artk yeni bir metakarakteri incelemeye baslayabiliriz.
10.2.4 + (Art)
Bu metakarakter, bir nceki metakarakterimiz olan * ile benzerdir. Hatrlarsanz, *
metakarakteri kendisinden nceki sfr veya daha fazla sayda tekrar eden karakterleri
ayklyordu. + metakarakteri ise kendisinden nceki bir veya daha fazla sayda tekrar eden
karakterleri ayklar. Bildiginiz gibi, nceki rneklerimizden birinde ahmet ve mehmet
gelerini su sekilde ayklamstk:
>>> for i in liste:
...
if re.match(".*met",i):
...
print i
Burada su komutu vermis olduk: Bana sonu met ile biten btn geleri ver! Ama bana
met gesini yalnz basna verme!
Ayn islemi search() metodunu kullanarak da yapabilecegimizi biliyorsunuz:
>>> for i in liste:
...
nesne = re.search(".+met",i)
...
if nesne:
...
nesne.group()
...
ahmet
mehmet
164
Burada yazdgmz dzenli ifadenin zelligi nedeniyle st de kapsama alan iine giriyordu.
nk burada * sembol a karakterinin hi bulunmadg durumlar da iine alyor. Ama
eger biz a karakteri en az bir kez gesin istiyorsak, dzenli ifademizi su sekilde yazmalyz:
>>> for i in yeniliste:
...
if re.match("sa+t", i):
...
print i
Hatrlarsanz nceki derslerimizden birinde kseli parantezi anlatrken syle bir rnek
vermistik:
>>> a = ["23BH56", "TY76Z", "4Y7UZ", "TYUDZ", "34534"]
>>> for i in a:
...
if re.match("[A-Z][A-Z][0-9]",i):
...
print i
Burada amacmz sadece TY76Z gesini almakt. Dikkat ederseniz, genin basndaki T
ve Y harflerini bulmak iin iki kez [A-Z] yazdk. Ama artk + metakarakterini
grendigimize gre ayn isi daha basit bir sekilde yapabiliriz:
>>> for i in a:
...
if re.match("[A-Z]+[0-9]",i):
...
print i
...
TY76Z
Burada [A-Z] dzenli ifade kalbn iki kez yazmak yerine bir kez yazp yanna da +
semboln koyarak, bu ifade kalbnn bir veya daha fazla sayda tekrar etmesini istedigimizi
belirttik...
+ sembolnn ne is yaptgn da anladgmza gre, artk yeni bir metakarakteri incelemeye
baslayabiliriz.
Hatrlarsanz, * karakteri sfr ya da daha fazla sayda eslesmeleri; + ise bir ya da daha
fazla sayda eslesmeleri kapsyordu. Iste simdi grecegimiz ? sembol de eslesme saysnn
sfr veya bir oldugu durumlar kapsyor. Bunu daha iyi anlayabilmek iin nceden verdigimiz
su rnege bakalm:
>>> yeniliste = ["st", "sat", "saat", "saaat", "falanca"]
>>> for i in yeniliste:
...
if re.match("sa*t",i):
...
print i
...
st
sat
saat
saaat
>>> for i in yeniliste:
10.2. Metakarakterler
165
...
...
...
sat
saat
saaat
if re.match("sa+t",i):
print i
de ?
sembolnn ne yaptgna bakalm:
>>> for i in yeniliste:
...
if re.match("sa?t",i):
...
print i
...
st
sat
bir rnek
verelim: Diyelim ki bir metin zerinde arama yapacaksnz. Aradgnz kelime uluslararas:
metin = """Uluslararas hukuk, uluslar aras ili
skiler altnda bir
disiplindir. Uluslararas ili
skilerin hukuksal boyutunu bilimsel bir
disiplin iinde inceler. Devletleraras hukuk da denir. Ancak uluslar
aras ili
skilere yeni aktrlerin giri
si bu dal sadece devletleraras
olmaktan karm
str."""
yapmak istedigimiz sey uluslararas kelimesini bulmak. Ama dikkat ederseniz metin
iinde uluslararas kelimesi ayn zamanda uluslar aras seklinde de geiyor. Bizim bu iki
kullanm da kapsayacak bir dzenli ifade yazmamz gerekecek...
>>> nesne = re.findall("[Uu]luslar ?aras", metin)
>>> for i in nesne:
...
print i
10.2.7 ^ (Sapka)
^ sembolnn iki islevi var. Birinci islevi, bir karakter dizisinin en basndaki veriyi
sorgulamaktr. Yani aslnda match() metodunun varsaylan olarak yerine getirdigi islevi bu
metakarakter yardmyla aka belirterek yerine getirebiliyoruz. Su
rnege bakalm:
>>> a = ['23BH56', 'TY76Z', '4Y7UZ', 'TYUDZ',
... '34534', '1agAY54']
>>> for i in a:
...
if re.search("[A-Z]+[0-9]",i):
...
print i
...
23BH56
TY76Z
4Y7UZ
1agAY54
10.2. Metakarakterler
167
Dikkat ederseniz, su son verdigimiz kod olduka hassas bir kt verdi bize. ktdaki btn
degerler, aynen dzenli ifademizde belirttigimiz gibi, yan yana bir veya daha fazla harf
ieriyor ve sonra da bir say ile devam ediyor. Bu farkllgn nedeni, ilk kodlarda print i
ifadesini kullanmamz. Bu durumun ktlarmz nasl degistirdigine dikkat edin. Bir de su
rnege bakalm:
>>> for i in a:
...
if re.match("[A-Z]+[0-9]",i):
...
print i
...
TY76Z
Burada sadece TY76Z ktsn almamzn nedeni, match() metodunun karakter dizilerinin
en basna bakyor olmas. Ayn etkiyi search() metoduyla da elde etmek iin, baslkta geen
^ (sapka) sembolnden yararlanacagz:
>>> for i in a:
...
nesne = re.search("^[A-Z]+[0-9]",i)
...
if nesne:
...
print nesne.group()
...
TY7
Grdgnz gibi, sapka sembol olmadgnda search() metodu karakter dizisinin basna
bakmakla yetinmiyor, ayn zamanda karakter dizisinin tamamn taryor. Biz yukardaki koda
bir ^ sembol ekleyerek, metodumuzun sadece karakter dizisinin en basna bakmasn
istedik. O da emrimize sadakatle uydu. Burada dikkatimizi ekmesi gereken baska bir nokta
168
da search() metodundaki ktnn krplms olmas. Dikkat ettiyseniz, search() metodu bize
genin tamamn vermedi. gelerin yalnzca [A-Z]+[0-9] kalbna uyan ksmlarn kesip
att nmze. nk biz ona tersini sylemedik. Eger gelerin tamamn istiyorsak bunu ak
ak belirtmemiz gerekir:
>>> for i in a:
...
nesne = re.search("[A-Z]+[0-9].\*",i)
...
if nesne:
...
print nesne.group()
...
BH56
TY76Z
Y7UZ
AY54
169
10.2.8 $ (Dolar)
Bir nceki blmde ^ isaretinin, karakter dizilerinin en basna demir attgn sylemistik.
Yani bu sembol arama/eslestirme isleminin karakter dizisinin en basndan baslamasn
saglyordu. Bu sembol bir bakma karakter dizilerinin nasl baslayacagn belirliyordu. Iste
simdi grecegimiz dolar isareti de ($) karakter dizilerinin nasl bitecegini belirliyor. Bu
soyut aklamalar somut bir rnekle baglayalm:
>>> liste = ["at", "katk", "fakat", "atk", "rahat",
... "mat", "yat", "sat", "satlk", "katlm"]
Grdgnz gibi, elimizde on gelik bir liste var. Diyelim ki biz bu listeden, at hecesiyle
biten kelimeleri ayklamak istiyoruz:
>>> for i in liste:
...
if re.search("at$",i):
...
print i
...
at
fakat
rahat
mat
yat
sat
Grdgnz gibi, ^ isareti bir karakter dizisinin nasl baslayacagn belirlerken, $ isareti
ayn karakter dizisinin nasl bitecegini belirliyor. Hatta istersek bu metakarakterleri birlikte de
kullanabiliriz:
>>> for i in liste:
...
if re.search("^at$",i):
...
print i
...
at
Sonu tam da bekledigimiz gibi oldu. Verdigimiz dzenli ifade kalb ile at ile baslayan ve
ayn sekilde biten karakter dizilerini aykladk. Bu da bize at ktsn verdi.
170
kadar grendigimiz
konulardan grdgnz gibi, Pythondaki dzenli ifadeler asndan zel anlam tasyan bir
takm semboller/metakarakterler var. Bunlar kendileriyle eslesmiyorlar. Yani bir karakter
dizisi iinde bu sembolleri aryorsak eger, bunlarn tasdklar zel anlam yznden bu
sembolleri ayklamak hemencecik mmkn olmayacaktr. Yani mesela biz $ semboln
aryor olsak, bunu Pythona nasl anlatacagz? nk bu sembol yazdgmz zaman Python
bunu farkl alglyor. Laf dolandrmadan hemen bir rnek verelim...
Diyelim ki elimizde syle bir liste var:
>>> liste = ["10$", "25C", "20$", "10TL", "25"]
deneyelim nce:
>>> for i in liste:
...
if re.match("[0-9]+$",i):
...
print i
Python $ isaretinin zel anlamndan dolay, bizim sayyla biten bir karakter dizisi
aradgmz zannedecek, dolaysyla da herhangi bir kt vermeyecektir. nk listemizde
sayyla biten bir karakter dizisi yok... Peki biz ne yapacagz? Iste bu noktada \
metakarakteri devreye girecek... Hemen bakalm:
>>> for i in liste:
...
if re.match("[0-9]+\$",i):
...
print i
...
10$
20$
10.2. Metakarakterler
171
mat
yat
sat
10.2.11 ( ) (Parantez)
Bu metakarakter yardmyla dzenli ifade kalplarn gruplayacagz. Bu metakarakter bizim
bir karakter dizisinin istedigimiz ksmlarn ayklamamzda ok byk kolaylklar saglayacak.
Diyelim ki biz http://www.istihza.com/py2/icindekiler_python.html adresindeki btn
baslklar ve bu baslklara ait html dosyalarn bir liste halinde almak istiyoruz. Bunun iin
syle bir sey yazabiliriz:
import re
import urllib
url = "http://www.istihza.com/py2/icindekiler_python.html"
f = urllib.urlopen(url)
for i in f:
nesne = re.search('href=".+html">.+</a>', i)
if nesne:
print nesne.group()
ifadenin bir veya daha fazla sayda tekrar eden eslesmelerini buluyor. Burada +
metakarakterinden nce gelen dzenli ifade, kendisi de bir metakarakter olan .
sembol... Bu sembol bildiginiz gibi, herhangi bir karakter anlamna geliyor.
Dolaysyla .+ ifadesi su demek oluyor: Bana bir veya daha fazla sayda tekrar eden
btn karakterleri bul! Dolaysyla burada (.+html) ifadesini birlikte dsnrsek,
yazdgmz sey su anlama geliyor: Bana html ile biten btn karakter dizilerini bul!
5. http://www.istihza.com/py2/icindekiler_python.html adresinin kaynagna baktgmz
zaman aradgmz bilgilerin hep su sekilde oldugunu gryoruz:
href=temel_bilgiler.html>1. Temel Bilgiler</a> Dolaysyla aslnda dzenli ifade
kalbmz yazarken yaptgmz sey, dzenli ifademizi kaynakta grnen sablona
uydurmak...
Yukarda verdigimiz kodlar alstrdgmz zaman aldgmz kt su sekilde oluyor:
href="http://www.istihza.com/py3/icindekiler_python.html">
suradaki</a>
href="temel_bilgiler.html">1. Temel Bilgiler</a>
...
Hemen hemen amacmza ulastk saylr. Ama grdgnz gibi ktmz biraz karmask.
Bunlar istedigimiz gibi dzenleyebilsek iyi olurdu, degil mi? Mesela bu ktlar su sekilde
dzenleyebilmek hos olurdu:
Ba
slk: ANA SAYFA; Ba
glant: index.html
Simdi
10.2. Metakarakterler
173
f = urllib.urlopen(url)
for i in f:
nesne = re.search('href="(.+html)">(.+)</a>',i)
if nesne:
print "Ba
slk: %s;\nBa
glant: %s\n" \
%(nesne.group(2), nesne.group(1))
Kodlarda yaptgmz degisikliklere dikkat edin ve anlamaya alsn. Baz noktalar gznze
karanlk grndyse hi endise etmeyin, nk bir sonraki blmde btn karanlk noktalar
tek tek aklayacagz. Burada en azndan, ( ) metakarakterini kullanarak dzenli ifadenin
baz blmlerini nasl grupladgmza dikkat edin.
Bu arada, elbette www.istihza.com sitesinde herhangi bir degisiklik olursa yukardaki kodlarn
istediginiz kty vermeyecegini bilmelisiniz. nk yazdgmz dzenli ifade istihza.com
sitesinin sayfa yapsyla sk skya baglantldr.
10.3 Esle
sme
Nesnelerinin Metotlar
10.3.1 group() metodu
Bu blmde dogrudan dzenli ifadelerin degil, ama dzenli ifadeler kullanlarak retilen
eslesme nesnelerinin bir metodu olan group() metodundan bahsedecegiz. Esasnda biz bu
metodu nceki blmlerde de kullanmstk. Ama burada bu metoda biraz daha ayrntl olarak
bakacagz.
Daha nceki blmlerden hatrlayacagnz gibi, bu metot dzenli ifadeleri kullanarak
eslestirdigimiz karakter dizilerini grme imkan saglyordu. Bu blmde bu metodu ()
metakarakteri yardmyla daha verimli bir sekilde kullanacagz. Isterseniz ilk olarak syle
basit bir rnek verelim:
>>> a = "python bir programlama dilidir"
>>> nesne = re.search("(python) (bir) (programlama) (dilidir)", a)
>>> print nesne.group()
python bir programlama dilidir
Burada dzenli ifade kalbmz nasl grupladgmza dikkat edin. print nesne.group()
komutunu verdigimizde eslesen karakter dizileri ekrana dkld. Simdi
bu grupladgmz
blmlere tek tek eriselim:
>>> print nesne.group(0)
python bir programlama dilidir
Grdgnz gibi, 0 indeksi eslesen karakter dizisinin tamamn veriyor. Bir de suna
bakalm:
174
Burada 1 numaral grubun gesi olan pythonu aldk. Gerisinin nasl olacagn tahmin
edebilirsiniz:
>>> print nesne.group(2)
bir
>>> print nesne.group(3)
programlama
>>> print nesne.group(4)
dilidir
Bu listede group() dsnda bir de groups() adl bir metodun oldugunu gryoruz. Simdi
bunun
ne is yaptgna bakalm.
Simdi
10.3. Esle
sme
Nesnelerinin Metotlar
175
print "Ba
slk: %s;\nBa
glant: %s\n" \
%(nesne.group(2),nesne.group(1))
176
5 Ocak
4 Ekim
Yukardaki rnekte, bir say ile baslayan, ardndan bir adet bosluk karakteri ieren, sonra da
bir byk veya kk harfle devam eden karakter dizilerini aykladk. Burada bosluk
karakterini \s simgesi ile gsterdigimize dikkat edin.
artk ayn islevi daha ksa yoldan, \d dizisi ile yerine getirebiliriz. Isterseniz yine
yukardaki rnekten gidelim:
>>> a =
>>> for
...
...
...
...
5 Ocak
4 Ekim
\w zel dizisinin hangi karakterleri esledigine dikkat edin. Bu zel dizi su ifadeyle ayn
anlama gelir:
[A-Za-z0-9_]
Dzenli ifadeler iindeki zel diziler genel olarak bunlardan ibarettir. Ama bir de bunlarn
byk harfli versiyonlar vardr ki, nemli olduklar iin onlar da inceleyecegiz.
Grdgnz gibi;
1. \s zel dizisi bosluk karakterlerini avlyor
2. \d zel dizisi ondalk saylar avlyor
3. \w zel dizisi alfanmerik karakterleri ve _ karakterini avlyor
177
Burada \S zel dizisinin listede belirtilen konumda bosluk iermeyen geyi nasl bulduguna
dikkat edin.
Simdi
Amacmz bu dosyada yer alan isim ve telefon numaralarn isim > telefon numaras
seklinde almak:
# -*- coding: utf-8 -*import re
dosya = open("adres.txt")
for i in dosya.readlines():
nesne = re.search("(\w+)\s+:\s(\w+)\s+(\d+)",i)
if nesne:
print "%s > %s"%(nesne.group(1), nesne.group(3))
Burada formlmz su sekilde: Bir veya daha fazla karakter + bir veya daha fazla bosluk
+ : isareti + bir adet bosluk + bir veya daha fazla say
Isterseniz bu blm ok basit bir soruyla kapatalm. Sorumuz su:
Elimizde su adresteki ygn var: http://www.istihza.com/denemeler/yigin.txt
Yapmanz gereken, bu ygn iindeki gizli mesaj dzenli ifadeleri kullanarak bulmak...
Cevaplarnz kistihza@yahoo. com adresine gnderebilirsiniz.
178
Burada ncelikle dzenli ifade kalbmz derledik. Derleme islemini nasl yaptgmza dikkat
edin. Derlenecek dzenli ifade kalbn compile() metodunda parantez iinde belirtiyoruz.
Daha sonra search() metodunu kullanrken ise, re.search() demek yerine, derli.search()
seklinde bir ifade kullanyoruz. Ayrca dikkat ederseniz derli.search() kullanmnda parantez
iinde sadece eslesecek karakter dizisini kullandk (i). Eger derleme islemi yapmams
olsaydk, hem bu karakter dizisini, hem de dzenli ifade kalbn yan yana kullanmamz
gerekecektir. Ama dzenli ifade kalbmz yukarda derleme islemi esnasnda belirttigimiz
iin, bu kalb ikinci kez yazmamza gerek kalmad. Ayrca burada kullandgmz dzenli ifade
kalbna da dikkat edin. Nasl bir sablon oturttugumuzu anlamaya alsn. Grdgnz gibi,
liste gelerinde bulunan . isaretini eslestirmek iin dzenli ifade kalb iinde \. ifadesini
kullandk. nk bildiginiz gibi, tek basna . isaretinin Python asndan zel bir anlam var.
Dolaysyla bu zel anlamdan kamak iin \ isaretini de kullanmamz gerekiyor.
Simdi
isterseniz kk bir rnek daha verelim. Diyelim ki amacmz gnlk dolar kurunu
almak olsun. Bu is iin http://www.tcmb.gov.tr/kurlar/today.html adresini kullanacagz:
# -*- coding: utf-8 -*import re
import urllib
f = urllib.urlopen("http://www.tcmb.gov.tr/kurlar/today.html")
derli = re.compile("ABD\sDOLARI\s+[0-9]\.[0-9]+")
179
nesne = derli.search(f.read())
print nesne.group()
Burada kullandgmz \s adl zel diziyi hatrlyorsunuz. Bu zel dizinin grevi karakter
dizileri iindeki bosluklarn yerini tutmakt. Mesela bizim rnegimizde ABD ve DOLARI
kelimeleri arasndaki boslugun yerini tutuyor. Ayrca yine DOLARI kelimesi ile 1 dolarn
TL karslg olan degerin arasndaki bosluklarn yerini de tutuyor. Yalnz dikkat ederseniz \s
ifadesi tek basna sadece bir adet boslugun yerini tutar. Biz onun birden fazla boslugun yerini
tutmas iin yanna bir adet + metakarakteri yerlestirdik. Ayrca burada da . isaretinin
yerini tutmas iin \. ifadesinden yararlandk.
Bu karakter dizisi iinde Python kelimesini temel alarak bir arama yapmak istiyorsak eger,
kullanacagmz su kod istedigimiz seyi yeterince yerine getiremeyecektir:
>>> print re.search("Python.*", a).group()
Burada alfanmerik karakterler ieren geleri ayklamaya alstk. Normalde ktmz ilek
fstk kebap seklinde olmalyd. Ama ilekteki ve fstktaki harfleri Trkeye
zg harfler oldugu iin dzenli ifade motoru bu harfleri tanmad.
10.5. Dzenli Ifadelerin Derlenmesi
181
stirme
kadar hep dzenli ifadeler yoluyla bir karakter dizisini nasl eslestirecegimizi
inceledik. Ama tabii ki dzenli ifadeler yalnzca bir karakter dizisi bulmakla ilgili degildir.
Bu ara ayn zamanda bir karakter dizisini degistirmeyi de kapsar. Bu is iin temel olarak iki
metot kullanlr. Bunlardan ilki sub() metodudur. Bu blmde sub() metodunu inceleyecegiz.
En basit sekliyle sub() metodunu su sekilde kullanabiliriz:
>>>
...
>>>
>>>
a = "Krmz ba
slkl kz, krmz elma dolu sepetiyle \
anneannesinin evine gidiyormu
s!"
derle = re.compile("krmz", re.IGNORECASE|re.UNICODE)
print derle.sub("ye
sil", a)
Burada karakter dizimiz iinde geen btn krmz kelimelerini yesil kelimesiyle
degistirdik. Bunu yaparken de re.IGNORECASE ve re.UNICODE adl derleme
seeneklerinden yararlandk. Bu ikisini yan yana kullanrken | adl metakarakterden
faydalandgmza dikkat edin.
Elbette sub() metoduyla daha karmask islemler yaplabilir. Bu noktada syle bir hatrlatma
yapalm. Bu sub() metodu karakter dizilerinin replace() metoduna ok benzer. Ama tabii ki
sub() metodu hem kendi basna replace() metodundan ok daha gldr, hem de beraber
kullanlabilecek derleme seenekleri sayesinde replace() metodundan ok daha esnektir. Ama
tabii ki, eger yapmak istediginiz is replace() metoduyla halledilebiliyorsa en dogru yol,
replace() metodunu kullanmaktr...
Simdi
bu sub() metodunu kullanarak biraz daha karmask bir islem yapacagz. Asagdaki
metne bakalm:
182
metin = Karadeniz Ereglisi denince akla ilk olarak kmr ve demir-elik gelir.
Kokusu ve tadyla dnyaya nam salms meshur Osmanl ilegi ise ismini verdigi
festival gnleri dsnda pek hatrlanmaz. Oysa inden Arnavutkye oradan da
Eregliye getirilen krallarn meyvesi ilek, burada geirdigi degisim sonucu tadna
doyulmaz bir hal alr. Ereglinin havasndan m suyundan m bilinmez, kokusu,
tad bambaska bir hale dnsr ve meshur Osmanl ilegi unvann hak eder. Bu
nazik ve aromal ilekten yaplan reel de likr de bir baska olur. Bu yl
dokuzuncusu dzenlenen Uluslararas Osmanl ilegi Kltr Festivalinde 36
retici arasnda yetistirdigi ileklerle birinci olan Kocaali Kynden Gner
zdemir, ylda bir ton rn alyor. 60 yasndaki zdemir, ileklerinin srrn
yogun ilgiye ve iten duydugu sevgiye baglyor: Erkekler bahemize giremez.
Koca ayaklaryla ezerler ileklerimizi ilegi toplamann zor oldugunu syleyen
Ayse zhan da ocuklugundan bu yana ilek bahesinde alsyor. Her sabah
04.00te kalkan zhan, ileklerini zenle suluyor. Kasm basnda ektigi ilek
fideleri haziran basnda meyve veriyor.
Not: Bu metin http://www.radikal.com.tr/haber.php?haberno=40130 adresinden alnmstr.
Gelin bu metin iinde geen ilek kelimelerini erik kelimesi ile degistirelim. Ama bunu
yaparken, metin iinde ilek kelimesinin ilek seklinde de getigine dikkat edelim.
Ayrca Trke kurallar geregi bu ilek kelimesinin baz yerlerde nsz yumusamasna
ugrayarak ileg- sekline dnstgn de unutmayalm.
Bu metin iinde geen ilek kelimelerini erikle degistirmek iin birka yol
kullanabilirsiniz. Birinci yolda, her degisiklik iin ayr bir dzenli ifade olusturulabilir. Ancak
bu yolun dezavantaj, metnin de birka kez kopyalanmasn gerektirmesidir. nk ilk dzenli
ifade olusturulup buna gre metinde bir degisiklik yapldktan sonra, ilk degisiklikleri ieren
metnin, farkl bir metin olarak kopyalanmas gerekir (metin2 gibi...). Ardndan ikinci
degisiklik yaplacag zaman, bu degisikligin metin2 zerinden yaplmas gerekir. Ayn sekilde
bu metin de, mesela, metin3 seklinde tekrar kopyalanmaldr. Bundan sonraki yeni bir
degisiklik de bu metin3 zerinden yaplacaktr... Bu durum bu sekilde uzar gider... Metni
tekrar tekrar kopyalamak yerine, dzenli ifadeleri kullanarak syle bir zm de retebiliriz:
# -*- coding: utf-8 -*import re
derle = re.compile("ile[k
g]", re.UNICODE|re.IGNORECASE)
def degistir(nesne):
a = {"ile
g":"eri
g", "ile
g":"Eri
g", "ilek":"Erik", "ilek":"erik"}
b = nesne.group().split()
for i in b:
return a[i]
print derle.sub(degistir,metin)
Grdgnz gibi, sub() metodu, argman olarak bir fonksiyon da alabiliyor. Yukardaki
kodlar biraz karsk grnms olabilir. Tek tek aklayalm...
Islemleri
stirme
10.6. Dzenli Ifadelerle Metin/Karakter Dizisi Degi
183
Burada amacmz, metin iinde geen ilek ve ileg kelimelerini bulmak. Neden ileg?
nk ilek kelimesi bir sesli harften nce geldiginde sonundaki k harfi gye dnsyor.
Bu seenekli yapy, daha nceki blmlerde grdgmz [ ] adl metakarakter yardmyla
olusturduk. Dzenli ifade kalbmzn hem byk harfleri hem de kk harfleri ayn anda
bulmas iin re.IGNORECASE seeneginden yararlandk. Ayrca Trke harfler zerinde
islem yapacagmz iin de re.UNICODE seenegini kullanmay unutmadk. Bu iki seenegi
| adl metakarakterle birbirine bagladgmza dikkat edin...
Simdi
de su satrlara bakalm:
def degistir(nesne):
a = {"ile
g":"eri
g", "ile
g":"Eri
g", "ilek":"Erik", "ilek":"erik"}
b = nesne.group().split()
for i in b:
return a[i]
Burada, daha sonra sub() metodu iinde kullanacagmz fonksiyonu yazyoruz. Fonksiyonu,
def degistir(nesne) seklinde tanmladk. Burada nesne adl bir argman kullanmamzn
nedeni, fonksiyon iinde group() metodunu kullanacak olmamz. Bu metodu fonksiyon iinde
nesne adl argmana baglayacagz. Bu fonksiyon, daha sonra yazacagmz sub() metodu
tarafndan agrldgnda, yaptgmz arama islemi sonucunda ortaya kan eslesme nesnesi
fonksiyona atanacaktr (eslesme nesnesinin ne demek oldugunu ilk blmlerden
hatrlyorsunuz). Iste nesne adl bir argman kullanmamzn nedeni de, eslesme nesnelerinin
bir metodu olan group() metodunu fonksiyon iinde kullanabilmek...
Bir sonraki satrda bir adet szlk gryoruz:
a = {"ile
g":"eri
g", "ile
g":"Eri
g", "ilek":"Erik", "ilek":"erik"}
Bu szlg olusturmamzn nedeni, metin iinde geen btn ilek kelimelerini tek bir
erik kelimesiyle degistiremeyecek olmamz... nk ilek kelimesi metin iinde pek ok
farkl biimde geiyor. Basta da dedigimiz gibi, yukardaki yol yerine metni birka kez
kopyalayarak ve her defasnda bir degisiklik yaparak da sorunu zebilirsiniz. (Mesela nce
ilek kelimelerini bulup bunlar erik ile degistirirsiniz. Daha sonra ileg kelimelerini
arayp bunlar erig ile degistirirsiniz, vb...) Ama metni tekrar tekrar olusturmak pek
performansl bir yntem olmayacaktr. Bizim simdi kullandgmz yntem metin kopyalama
zorunlulugunu ortadan kaldryor. Bu szlk iinde ilek kelimesinin alacag sekilleri
szlk iinde birer anahtar olarak, erik kelimesinin alacag sekilleri ise birer deger olarak
belirliyoruz. Bu arada GNU/Linux kullanclar Trke karakterleri dzgn
grntleyebilmek iin bu szlkteki geleri unicode olarak belirliyor (uerik gibi...)
Sonraki satrda iki metot birden var:
b = nesne.group().split()
Burada, fonksiyonumuzun argman olarak vazife gren eslesme nesnesine ait metotlardan
biri olan group() metodunu kullanyoruz. Bylece derle =
re.compile(ile[kg],re.UNICODE|re.IGNORECASE) satr yardmyla metin iinde
184
Bu kty grdkten sonra, kodlarda yapmaya alstgmz sey daha anlaml grnmeye
baslams olmal... Simdi
Burada, group() metodu yardmyla buldugumuz eslesmeler zerinde bir for dngs
olusturduk. Ardndan da return a[i] komutunu vererek a adl szlk iinde yer alan geleri
yazdryoruz. Bu arada, buradaki inin yukarda verdigimiz group() ktlarn temsil ettigine
dikkat edin. a[i] gibi bir komut verdigimizde aslnda srasyla su komutlar vermis oluyoruz:
a["ilek"]
a["ile
g"]
a["ilek"]
a["ile
g"]
a["ilek"]
a["ilek"]
a["ilek"]
a["ile
g"]
a["ilek"]
a["ilek"]
Bu komutlarn ktlar srasyla erik, erig, erik, Erig, erik, erik, erik, Erig,
erik, erik olacaktr. Iste bu return satr bir sonraki kod olan print derle.sub(degistir,metin)
ifadesinde etkinlik kazanacak. Bu son satrmz szlk gelerini tek tek metne uygulayacak ve
mesela a[ilek] komutu sayesinde metin iinde ilek grdg yerde erik kelimesini
yapstracak ve bylece bize istedigimiz sekilde degistirilmis bir metin verecektir...
Bu kodlarn biraz karsk gibi grndgn biliyorum, ama aslnda ok basit bir mantg var:
group() metodu ile metin iinde aradgmz kelimeleri ayklyor. Ardndan da a szlg
iinde bunlar anahtar olarak kullanarak ilek ve esitleri yerine erik ve esitlerini
koyuyor...
Yukarda verdigimiz dzenli ifadeyi byle ufak bir metinde kullanmak ok anlaml
Islemleri
stirme
10.6. Dzenli Ifadelerle Metin/Karakter Dizisi Degi
185
10.7 Sonu
Bylelikle dzenli ifadeler konusunu bitirmis olduk. Buradaki amacmz, size dzenli ifadeler
konusunda genel bir baks sunabilmekti. Bu yazlar okuduktan sonra kafanzda dzenli
ifadelerle ilgili kabataslak da olsa bir resim olustuysa bu yazlar amacna ulasms demektir.
Elbette dzenli ifadeler burada anlattklarmzdan ibaret degildir. Bu konunun zerine
egildiginizde aslnda dzenli ifadelerin dipsiz bir kuyu gibi oldugunu greceksiniz. Esasnda
en basta da dedigimiz gibi, dzenli ifadeler apayr bir dil gibidir. Dogrusu su ki, dzenli
ifadeler basl basna bagmsz bir sistemdir. Hemen hemen btn programlama dilleri yle ya
da byle dzenli ifadeleri destekler. Pythonda dzenli ifadeleri bnyesine adapte etmis
dillerden biridir. Bizim dzenli ifadeler konusundaki yaklasmmz, her zaman bunlar
gerektiginde kullanmak olmaldr. Dedigimiz gibi, eger yapmak istediginiz bir islemi
karakter dizilerinin metotlar yardmyla yapabiliyorsanz dzenli ifadelere girismemek en
iyisidir. nk karakter dizisi metotlar hem daha hzldr hem de anlamas daha kolaydr.
186
BLM 11
187
11.2 Snflar
NTPde en nemli kavram snflardr. Zaten NTP denince ilk akla gelen sey de genellikle
snflar olmaktadr. Snflar yap olarak fonksiyonlara benzetilebilir. Hatrlarsanz,
fonksiyonlar yardmyla farkl degiskenleri ve veri tiplerini, tekrar kullanlmak zere bir yerde
toplayabiliyorduk. Iste snflar yardmyla da farkl fonksiyonlar, veri tiplerini, degiskenleri,
metotlar gruplandrabiliyoruz.
Bylece snflar olusturmak iin ilk adm atms olduk. Burada dikkat etmemiz gereken baz
noktalar var:
Hatrlarsanz fonksiyonlar tanmlarken def paracgndan yararlanyorduk. Mesela:
def deneme():
Tpk fonksiyonlarda oldugu gibi, isim olarak herhangi bir kelimeyi seebiliriz. Mesela
yukardaki fonksiyonda deneme adn semistik. Yine yukarda grdgmz snf rneginde
de IlkSinif adn kullandk. Tabii isim belirlerken Trke karakter kullanamyoruz.
188
Snf adlarn belirlerken kullanacagmz kelimenin byk harf veya kk harf olmas nemli
degildir. Ama seilen kelimelerin ilk harflerini byk yazmak adettendir. Mesela class Sinif
veya class HerhangiBirKelime. Grdgnz gibi snf ad birden fazla kelimeden olusuyorsa
her kelimenin ilk harfi byk yazlyor. Bu bir kural degildir, ama her zaman adetlere uymak
yerinde bir davrans olacaktr.
Son olarak, snfmz tanmladktan sonra parantez isareti kullanmak zorunda olmadgmza
dikkat edin. En azndan simdilik... Bu parantez meselesine tekrar dnecegiz.
Ilk adm attgmza gre ilerleyebiliriz:
class IlkSinif:
mesele = "Olmak ya da olmamak"
Bylece eksiksiz bir snf tanmlams olduk. Aslnda tabii ki normalde snflar bundan biraz
daha karmasktr. Ancak yukardaki rnek, gerek hayatta bu haliyle karsmza kmayacak da
olsa, hem yap olarak kurallara uygun bir snftr, hem de bize snflara iliskin pek ok nemli
ipucu vermektedir. Srasyla bakalm:
Ilk satrda dogru bir sekilde snfmz tanmladk.
Ikinci satrda ise mesele adl bir degisken olusturduk.
Bylece ilk snfmz basaryla tanmlams olduk.
Simdi
Burada sizin bu kodlar sinif.py adl bir dosyaya kaydettiginizi varsaydm. Dolaysyla bu
sekilde dosyamz bir modl olarak ie aktarabiliyoruz (import). Bu arada Pythonun bu
modl dzgn olarak ie aktarabilmesi iin komut satrn, bu modln bulundugu dizin
iinde amak gerekir. Python ie aktarlacak modlleri ararken ilk olarak o anda iinde
bulunulan dizine bakacag iin modlmz rahatlkla bulabilecektir.
11.2. Snflar
189
GNU/Linux kullanclar komut satryla daha ili dsl olduklar iin etkilesimli kabugu
modln bulundugu dizinde nasl aacaklarn zaten biliyorlardr... Ama biz yine de hzlca
zerinden geelim. (Modln masastnde oldugunu varsayyoruz):
ALT+F2 tuslarna basp alan pencereye konsole (KDE) veya gnome-terminal (GNOME)
yazyoruz. Ardndan konsol ekrannda cd Desktop komutunu vererek masastne erisiyoruz.
Windows kullanclarnn komut satrna daha az asina oldugunu varsayarak biraz daha detayl
anlatalm bu islemi...
Windows kullanclar ise Python komut satrn modln oldugu dizin iinde amak iin su
yolu izleyebilir (yine modln masastnde oldugunu varsayarsak...):
Baslat/alstr yolunu takip edip alan kutuya cmd yazyoruz (parantezler olmadan).
Komut ekran karsmza gelecek. Muhtemelen iinde bulundugunuz dizin C:Documents and
Settings/Isminiz olacaktr. Orada su komutu vererek masastne geiyoruz:
cd Desktop
Simdi
Tabii kullandgnz Python srmnn 2.7 oldugunu varsaydm. Sizde srm farklysa
komutu ona gre degistirmelisiniz.
Eger herhangi bir hata yapmadysanz karsnza suna benzer bir ekran gelmeli:
Python 2.7.4 (default, Apr 6 2013, 19:54:46)
[MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license"
or more information.
>>>
Simdi
Artk snfmz alstrmamzn nnde hi bir engel kalmad saylr. Bu noktada yapmamz
gereken tek bir islem var: rnekleme
Bylece olusturdugumuz snf bir degiskene atadk. NTP kavramlaryla konusacak olursak,
snfmz rneklemis olduk.
Peki bu rnekleme denen sey de ne oluyor? Hemen bakalm:
Ingilizcede instantiation olarak ifade edilen rnekleme kavram sayesinde snfmz
kullanrken belli bir kolaylk saglams oluyoruz. Grdgnz gibi, rnekleme (instantiation)
190
aslnda sekil olarak yalnzca bir degisken atama isleminden ibarettir. Nasl daha nce
grdgmz degiskenler uzun ifadeleri ksaca adlandrmamz saglyorsa, burada da
rnekleme islemi hemen hemen ayn vazifeyi gryor. Yani bylece ilk satrda tanmladgmz
snfa daha kullansl bir isim vermis oluyoruz. Dedigimiz gibi, bu isleme rnekleme
(instantiation) ad veriliyor. Bu rneklemelerin her birine ise rnek (instance) deniyor. Yani,
IlkSinif adl snfa bir isim verme islemine rnekleme denirken, bu islem sonucu ortaya
kan degiskene de, rnek (instance) diyoruz. Buna gre, burada deneme adl degisken,
IlkSinif adl snfn bir rnegidir. Daha soyut bir ifadeyle, rnekleme islemi Class (snf)
nesnesini etkinlestirmeye yarar. Yani snfn btnn alr ve onu paketleyip, istedigimiz
sekilde kullanabilecegimiz bir nesne haline getirir. Syle
de diyebiliriz:
Biz bir snf tanmlyoruz. Bu snfn iinde birtakm degiskenler, fonksiyonlar, vb. olacaktr.
Hayli kaba bir benzetme olacak ama, biz bunlar bir internet sayfasnn ierigine
benzetebiliriz. Iste biz bu snf rnekledigimiz zaman, snf ierigini bir bakma erisilebilir
hale getirmis oluyoruz. Tpk bir internet sayfasnn, www.... seklinde gsterilen adresi
gibi... Mesela www.istihza.com adresi iindeki btn bilgileri bir snf olarak dsnrsek,
www.istihza.com ifadesi bu snfn bir rnegidir... Durum tam olarak byle olmasa bile, bu
benzetme, rnekleme islemine iliskin en azndan zihnimizde bir kvlcm akmasn
saglayabilir.
Daha yerinde bir benzetme syle olabilir: Insan byk bir snf olarak kabul edelim. Iste
siz (yani Ahmet, Mehmet, vb...) bu byk snfn bir rnegi, yani ete kemige brnms hali
oluyorsunuz... Buna gre insan snf insann ne tr zellikleri olduguna dair tanmlar
(fonksiyonlar, veriler) ieriyor. Mehmet rnegi (instance) ise bu tanmlar, nitelikleri,
zellikleri tasyan bir nesne oluyor...
191
oldugu gibi snflarmz rneklemezsek, bu snflara hibir yerde isaret edilmedigi, yani bu
snf gsteren hibir referans olmadg iin, snfmz olusturuldugu anda p toplama
islemine tabi tutulacaktr. Dolaysyla artk bellekte tutulmayacaktr.
p toplama islemini de ksaca anlattgmza gre artk kaldgmz yerden yolumuza devam
edebiliriz...
Bu arada dikkat ettiyseniz snfmz rneklerken parantez kullandk. Yani syle yaptk:
>>> deneme = IlkSinif()
Eger parantezleri kullanmazsak, yani deneme = IlkSinif gibi bir sey yazarsak, yaptgmz sey
rnekleme olmaz. Byle yaparak snf sadece kopyalams oluruz. Bizim yapmak istedigimiz
bu degil. O yzden, parantezlere dikkat! diyoruz...
Artk su komut yardmyla, snf rnegimizin niteliklerine ulasabiliriz:
>>> deneme.mesele
Olmak ya da olmamak
dedigimiz zaman, buradaki mesele; deneme adl snf rneginin (instance) bir niteligi
(attribute) oluyor. Biraz karsk gibi mi? Hemen bir rnek yapalm o halde:
class Toplama:
a = 15
b = 20
c = a + b
Ilk satrda Toplama adl bir snf tanmladk. Bunu yapmak iin class paracgndan
yararlandk. Srasyla; a, b ve c adl adet degisken olusturduk. c degiskeni a ve b
degiskenlerinin toplamdr.
Bu snftaki a, b ve c degiskenleri ise, Toplama snf rneginin birer niteligi oluyor. Bundan
nceki rnegimizde ise mesele adl degisken, deneme adl snf rneginin bir niteligi idi...
Bu snf yazp kaydettigimiz dosyamzn adnn matematik.py oldugunu varsayarsak;
192
Eger modl bu sekilde ie aktarrsak (import), snf rneginin niteliklerine ulasmak iin su
yapy kullanmamz gerekir:
>>> matematik.sonuc.a
>>> matematik.sonuc.b
>>> matematik.sonuc.c
Yani her defasnda dosya adn (ya da baska bir ifadeyle modln adn) da belirtmemiz
gerekir. Bu iki kullanm arasnda, zellikle sagladklar gvenlik avantajlar/dezavantajlar
asndan baska baz temel farkllklar da vardr, ama simdilik konumuzu dagtmamak iin
bunlara girmiyoruz... Ama temel olarak sunu bilmekte fayda var: Genellikle tercih edilmesi
gereken yntem from modl import * yerine import modl biimini kullanmaktr. Eger from
modl import * yntemini kullanarak ie aktardgnz modl iindeki isimler (degiskenler,
nitelikler), bu modl kullanacagnz dosya iinde de bulunuyorsa isim aksmalar ortaya
kabilir... Esasnda, from modl import * yapsn sadece ne yaptgmz ok iyi biliyorsak ve
modlle ilgili belgelerde modln bu sekilde ie aktarlmas gerektigi bildiriliyorsa
kullanmamz yerinde olacaktr. Mesela Tkinter ile programlama yaparken rahatlkla from
Tkinter import * yapsn kullanabiliriz, nk Tkinter bu kullanmda problem yaratmayacak
sekilde tasarlanmstr. Yukarda bizim verdigimiz rnekte de from modl import * yapsn
rahatlkla kullanyoruz, nk simdilik tek bir modl zerinde alsyoruz. Dolaysyla isim
aksmas yaratacak baska bir modlmz olmadg iin ne yaptgmz biliyoruz!...
Yukarda anlattgmz kod alstrma biimleri tabii ki, bu kodlar komut ekranndan
alstrdgnz varsaymaktadr. Eger siz bu kodlar IDLE ile alstrmak isterseniz, bunlar
hazrladktan sonra F5 tusuna basmanz, veya Run/Run Module yolunu takip etmeniz yeterli
olacaktr. F5 tusuna bastgnzda veya Run/Run Module yolunu takip ettiginizde IDLE
sanki komut ekrannda from matematik import * komutunu vermissiniz gibi davranacaktr.
Veya GNU/Linux sistemlerinde sistem konsolunda:
11.2. Snflar
193
python -i sinif.py
Toplama adl bir snf tanmlyoruz. Snfmzn iine istedigimiz kod paralarn ekliyoruz.
Biz burada adet degisken ekledik. Bu degiskenlerin her birine, nitelik adn veriyoruz.
Bu kodlar kullanabilmek iin Python komut satrnda su komutu veriyoruz:
>>> from matematik import *
yapmamz gereken sey, Toplama adl snf rneklemek (instantiation). Yani bir nevi,
snfn kendisini bir degiskene atamak... Bu degiskene biz Pythoncada rnek (instance) adn
veriyoruz. Yani, sonuc adl degisken, Toplama adl snfn bir rnegidir diyoruz:
>>> sonuc = Toplama()
Dikkat ederseniz, niteliklerimize erisirken rnekten (instance), yani sonuc adl degiskenden
yararlanyoruz.
Simdi
Ama daha nce de anlattgmz gibi, siz Toplama().a der demez snf alstrlacak ve
alstrldktan hemen sonra ortada bu snfa isaret eden herhangi bir referans kalmadg iin
Python tarafndan ise yaramaz olarak alglanan snfmz p toplama islemine tabi tutularak
derhal bellegi terketmesi saglanacaktr. Bu yzden bunu her alstrdgnzda yeniden bellege
yklemis olacaksnz snf. Bu da bir hayli verimsiz bir alsma seklidir.
Bylelikle zor ksm geride brakms olduk. Artk nmze bakabiliriz. Zira en temel baz
kavramlar gzden geirdigimiz ve temelimizi olusturdugumuz iin, daha karsk seyleri
anlamak kolaylasacaktr.
194
Biz simdilik bu yapdaki __init__ ksmyla ilgilenecegiz. selfin ne oldugunu simdilik bir
kenara brakp, onu oldugu gibi kabul edelim. Ise hemen bir rnekle baslayalm. Isterseniz
kendimizce ufack bir oyun tasarlayalm:
#!/usr/bin/env python
# -*- coding: utf-8 -*class Oyun:
def __init__(self):
enerji = 50
para = 100
fabrika = 4
isci = 10
print "enerji:", enerji
print "para:", para
print "fabrika:", fabrika
print "i
si:", isci
macera = Oyun()
Gayet gzel. Dikkat ederseniz rnekleme (instantiation) islemini dogrudan dosya iinde
hallettik. Komut satrna brakmadk bu isi.
Simdi
Burada dosya adnn deneme.py oldugunu varsaydk. Eger rnekleme islemini dosya
iinden halletmemis olsaydk, from deneme import * komutunu vermeden nce macera =
Oyun() satr yardmyla ilk olarak snfmz rneklendirmemiz gerekecekti.
GNU/Linux sistemlerinde baska bir seenek olarak, ALT+F2 tuslarna basyoruz ve alan
pencerede konsole (KDE) veya gnome-terminal (GNOME) yazp ENTER tusuna
bastktan sonra atgmz komut satrnda su komutu veriyoruz:
python -i deneme.py
Eger Windowsta IDLE zerinde alsyorsak, F5 tusuna basarak veya Run/Run Module
yolunu takip ederek kodlarmz alstryoruz.
Bu kodlar yukardaki seeneklerden herhangi biriyle alstrdgmzda, __init__ fonksiyonu
iinde tanmlanms olan btn degiskenlerin, yani niteliklerin, ilk alsma esnasnda ekrana
yazdrldgn gryoruz. Iste bu niteliklerin baslang degeri olarak belirlenebilmesi hep
__init__ fonksiyonu sayesinde olmaktadr. Dolaysyla syle bir sey diyebiliriz:
11.2. Snflar
195
Pythonda bir programn ilk kez alstrldg anda islemesini istedigimiz seyleri bu __init__
fonksiyonu iine yazyoruz. Mesela yukardaki ufak oyun alsmasnda, oyuna baslandg
anda bir oyuncunun sahip olacag zellikleri __init__ fonksiyonu iinde tanmladk. Buna
gre bu oyunda bir oyuncu oyuna basladgnda:
enerjisi 50, paras 100, fabrika says 4, isi says ise 10 olacaktr.
Yalnz hemen uyaralm: Yukardaki rnek aslnda pek de dzgn saylmaz. ok nemli
eksiklikleri var bu kodun. Ama simdi konumuz bu degil... Olayn i yzn kavrayabilmek
iin yle bir rnek vermemiz gerekiyordu. Bunu biraz sonra aklayacagz. Biz okumaya
devam edelim...
Bir de Tkinter ile bir rnek yapalm. Zira snfl yaplarn en ok ve en verimli kullanldg yer
arayz programlama alsmalardr:
from Tkinter import *
class Arayuz:
def __init__(self):
pencere = Tk()
dugme = Button(text="tamam")
dugme.pack()
pencere.mainloop()
uygulama = Arayuz()
196
Diyelim ki biz burada enerji, para, fabrika, isi degiskenlerini ayr bir fonksiyon iinde
kullanmak istiyoruz. Yani mesela gster() adl ayr bir fonksiyonumuz olsun ve biz bu
degiskenleri ekrana yazdrmak istedigimizde bu gster() fonksiyonundan yararlanalm.
Kodlarn su anki halinde oldugu gibi, bu kodlar tanmlansn, ama dogrudan ekrana
dklmesin. Syle
macera.enerji
macera.para
macera.fabrika
macera.isci
macera.goster()
Hemen deneyelim. Ama o da ne? Mesela macera.goster() dedigimizde syle bir hata alyoruz:
11.2. Snflar
197
Belli ki bir hata var kodlarmzda. goster() fonksiyonuna bir self ekleyerek tekrar
deneyelim. Belki dzelir:
class Oyun:
def __init__(self):
enerji = 50
para = 100
fabrika = 4
isci = 10
def goster(self):
print "enerji:", enerji
print "para:", para
print "fabrika:", fabrika
print "i
si:", isci
macera = Oyun()
Tekrar deniyoruz:
>>> macera.goster()
Hmm... Sorunun ne oldugu az ok ortaya kt. Hatrlarsanz buna benzer hata mesajlarn
fonksiyon tanmlarken global degiskeni yazmadgmz zamanlarda da alyorduk. Iste self
burada devreye giriyor. Yani bir bakma, fonksiyonlardaki global ifadesinin yerini tutuyor.
Daha dogru bir ifadeyle, burada macera adl snf rnegini temsil ediyor. Artk kodlarmz
dzeltebiliriz:
class Oyun:
def __init__(self):
self.enerji = 50
self.para = 100
self.fabrika = 4
self.isci = 10
def goster(self):
print "enerji:", self.enerji
198
macera.enerji
macera.para
macera.isci
macera.fabrika
Eger biz enerji adl degiskeni goster() fonksiyonu iinde kullanmak istersek degiskeni
sadece enerji degil, self.enerji olarak tanmlamamz gerekir. Ayrca bunu goster() adl
fonksiyon iinde kullanrken de sadece enerji olarak degil, self.enerji olarak yazmamz
gerekir. stelik mesela enerji adl degiskeni herhangi bir yerden agrmak istedigimiz
zaman da bunu nceden self olarak tanmlams olmamz gerekir.
Simdi
tekrar deneyelim:
>>> macera.goster
enerji: 50
para: 100
fabrika: 4
i
si: 10
>>> macera.enerji
50
>>> macera.para
100
>>> macera.fabrika
4
>>> macera.isci
10
Snfn niteliklerine tek tek nasl erisebildigimizi gryorsunuz. Bu arada, isterseniz selfi,
11.2. Snflar
199
macera rneginin yerini tutan bir kelime olarak da kurabilirsiniz zihninizde. Yani kodlar
alstrrken macera.enerji diyebilmek iin, en basta bunu self.enerji olarak tanmlamamz
gerekiyor... Bu dsnme tarz isimizi biraz daha kolaylastrabilir.
Bir de Tkinterli rnegimize bakalm:
from Tkinter import *
class Arayuz:
def __init__(self):
pencere = Tk()
dugme = Button(text="tamam")
dugme.pack()
pencere.mainloop()
uygulama = Arayuz()
Bunun sebebini bir nceki rnekte grenmistik. Kodlarmz su sekilde yazmamz gerekiyor:
# -*- coding: utf-8 -*from Tkinter import *
class Arayuz:
def __init__(self):
200
pencere = Tk()
dugme = Button(text="tamam", command=self.yaz)
dugme.pack()
pencere.mainloop()
def yaz(self):
print "Gr
smek zere!"
uygulama = Arayuz()
Ama siz byle yapmayn. self kelimesinin kullanm o kadar yaygnlasms ve yerlesmistir
ki, sizin bunu kendi kodlarnzda dahi olsa degistirmeye kalkmanz pek hos
karslanmayacaktr. Ayrca sizin kodlarnz okuyan baskalar, ne yapmaya alstgnz
anlamakta bir an da olsa tereddt edecektir. Hatta birka yl sonra dnp siz dahi ayn kodlara
baktgnzda, Ben burada ne yapmaya alsmsm? diyebilirsiniz.
Sizi self kullanmaya ikna ettigimizi kabul edersek, artk yolumuza devam edebiliriz.
Hatrlarsanz yukarda ufack bir oyun alsmas yapmaya baslamstk. Gelin isterseniz
oyunumuzu biraz ayrntlandralm. Elimizde simdilik sunlar vard:
11.2. Snflar
201
class Oyun:
def __init__(self):
self.enerji = 50
self.para = 100
self.fabrika = 4
self.isci = 10
def goster(self):
print "enerji:", self.enerji
print "para:", self.para
print "fabrika:", self.fabrika
print "i
si:", self.isci
macera = Oyun()
Buradaki kodlar yardmyla bir oyuncu olusturduk. Bu oyuncunun oyuna basladgnda sahip
olacag enerji, para, fabrika ve isi bilgilerini de girdik. Kodlarmz arasndaki goster()
fonksiyonu yardmyla da her an bu bilgileri grntleyebiliyoruz.
Simdi
isterseniz oyunumuza biraz hareket getirelim. Mesela kodlara yeni bir fonksiyon
ekleyerek oyuncumuza yeni fabrikalar kurma olanag tanyalm:
class Oyun:
def __init__(self):
self.enerji = 50
self.para = 100
self.fabrika = 4
self.isci = 10
def goster(self):
print "enerji:", self.enerji
print "para:", self.para
print "fabrika:", self.fabrika
print "i
si:", self.isci
def fabrikakur(self, miktar):
if self.enerji > 3 and self.para > 10:
self.fabrika = miktar + self.fabrika
self.enerji = self.enerji - 3
self.para = self.para - 10
print miktar, "adet fabrika kurdunuz! Tebrikler!"
else:
print "Yeni fabrika kuramazsnz. \
Yeterli enerjiniz/paranz yok!"
macera = Oyun()
202
>>> macera.fabrikakur(5)
Bu komutu verdigimizde, 5 adet fabrika kurdunuz! Tebrikler! seklinde bir kutlama mesaj
gsterecektir bize programmz. . . Kodlarmz iindeki def fabrikakur(self,miktar) ifadesinde
grdgmz miktar kelimesi, kodlar alstrrken verecegimiz parametreyi temsil ediyor.
Yani burada 5 saysn temsil ediyor. Eger macera.fabrikakur() fonksiyonunu kullanrken
herhangi bir say belirtmezseniz, hata alrsnz. nk kodlarmz tanmlarken fonksiyon
iinde miktar adl bir ifade kullanarak, kullancdan fonksiyona bir parametre vermesini
bekledigimizi belirttik. Dolaysyla Python kullancdan parantez iinde bir parametre
girmesini bekleyecektir. Eger fonksiyon parametresiz alstrlrsa da, Pythonun beklentisi
karslanmadg iin hata verecektir. Burada dikkat edecegimiz nokta, kodlar iinde bir
fonksiyon tanmlarken ilk parametrenin her zaman self olmas gerektigidir. Yani def
fabrikakur(miktar) degil, def fabrikakur(self, miktar) dememiz gerekiyor.
Simdi
de su komutu verelim:
>>> macera.goster()
enerji: 47
para: 90
fabrika: 9
i
si: 10
Grdgnz gibi oyuncumuz 5 adet fabrika kazanms, ama bu islem enerjisinde ve parasnda
bir miktar kayba neden olmus (fabrika kurmay bedava m sandnz!).
Yazdgmz kodlara dikkatlice bakarsanz, oradaki if deyimi sayesinde oyuncunun enerjisi
3n altna, paras da 10un altna dserse syle bir mesaj verilecektir:
"Yeni fabrika kuramazsnz. Yeterli enerjiniz/paranz yok!"
kadar bir oyuncu olusturduk ve bu oyuncuya oyuna basladg anda sahip olacag baz
zellikler verdik. Olusturdugumuz oyuncu isterse oyun iinde fabrika da kurabiliyor. Ama
byle, kendin al, kendin oyna tarz bir durumun skc olacag belli. O yzden gelin oyuna
biraz hareket katalm! Mesela oyunumuzda bir adet oyuncu dsnda bir adet de dsman olsun.
O halde hemen bir adet dsman olusturalm:
class Dusman:
11.2. Snflar
203
enerjisi 50,
paras 100,
fabrika says 4,
i
si says ise 10
olsun. Simdi
Simdi
ayn seyi Dusman snf iin de yapacagz. Peki bu zellikleri yeniden tek tek
dsman iin de yazacak myz? Tabii ki, hayr. O halde nasl yapacagz bunu? Iste burada
imdadmza Python snflarnn miras alma zelligi yetisiyor. Yabanclar bu kavrama
inheritance adn veriyorlar. Yani, nasl Msrdaki dedenizden size miras kaldgnda
dedenizin size braktg mirasn nimetlerinden her ynyle yararlanabiliyorsanz, bir snf
baska bir snftan miras aldgnda da ayn sekilde miras alan snf miras aldg snfn
zelliklerini kullanabiliyor. Az laf, ok is. Hemen bir rnek yapalm. Yukarda Dusman adl
snfmz olusturmustuk:
class Dusman:
Dusman snf henz bu haliyle hibir sey miras alms degil. Hemen miras aldralm. Bunun
iin snfmz syle tanmlamamz gerekiyor:
class Dusman(Oyun):
Yukarda pass ifadesini neden kullandgmz biliyorsunuz. Snf tanmladktan sonra iki
nokta st stenin ardndan asagya bir kod blogu yazmamz gerekiyor. Ama su anda oraya
yazacak bir kodumuz yok. O yzden idareten oraya bir pass ifadesi yerlestirerek gerekli kod
blogunu geistirmis oluyoruz. O ksm bos brakamayz. Yoksa snfmz kullanlamaz
durumda olur. Daha sonra oraya yazacagmz kod bloklarn hazrladktan sonra oradaki pass
ifadesini silecegiz.
Simdi
204
snfmz daha nce tanmladgmz Oyun adl snf miras alyor. Dolaysyla Dusman adl
snf Oyun adl snfn btn zelliklerine sahip. Bunu hemen test edelim:
>>> dsman.goster()
enerji: 50
para: 100
fabrika: 4
i
si: 10
Grdgnz gibi, Oyun snfnn bir fonksiyonu olan goster()i Dusman snf iinden de
alstrabildik. stelik Dusman iinde bu degiskenleri tekrar tanmlamak zorunda kalmadan...
Istersek bu degiskenlere teker teker de ulasabiliriz:
>>> dsman.enerji
50
>>> dsman.isci
10
Dusman snf ayn zamanda Oyun snfnn fabrikakur() adl fonksiyonuna da erisebiliyor:
>>> dsman.fabrikakur(4)
4 adet fabrika kurdunuz! Tebrikler!
Evet, dsmanmzn fabrika says artms, enerjisi ve paras azalms. Bir de kendi
durumumuzu kontrol edelim:
>>> macera.goster()
enerji: 50
para: 100
fabrika: 4
i
si: 10
11.2. Snflar
205
Dsmanmzn, oyuncunun zelliklerine ek olarak bir de ego adl bir niteligi olsun. Mesela
dsmanmz bize her zarar verdiginde egosu bysn!
nce syle deneyelim:
class Dusman(Oyun):
def __init__(self):
self.ego = 0
Burada Oyun.__init__(self) ifadesiyle Oyun adl snfn __init__ fonksiyonu iinde yer alan
btn nitelikleri, Dusman adl snfn __init__ fonksiyonu iine kopyalyoruz. Bylece
self.ego degiskenini tanmlarken, enerji, para, vb. niteliklerin kaybolmasn engelliyoruz.
Aslnda bu haliyle kodlarmz dzgn sekilde alsr.
Kodlarmz alstrdgmzda biz ekranda gremesek de aslnda ego adl nitelige sahiptir
dsmanmz. Ekranda bunu gremememizin nedeni tabii ki kodlarmzda henz bu niteligi
ekrana yazdracak bir print deyiminin yer almamas... Isterseniz bu zelligi daha nce de
yaptgmz gibi ayr bir fonksiyon ile halledelim:
class Dusman(Oyun):
def __init__(self):
Oyun.__init__(self)
self.ego = 0
def goster(self):
Oyun.goster(self)
print "ego:", self.ego
dsman = Dusman()
206
i
si: 10
ego: 0
Grdgnz gibi dsmanmzn zellikleri arasnda oyuncumuza ilave olarak bir de ego adl
bir nitelik var. Bunun baslang degerini 0 olarak ayarladk. Daha sonra yazacagmz
fonksiyonda dsmanmz bize zarar verdike egosu byyecek. Simdi
gelin bu fonksiyonu
yazalm:
class Dusman(Oyun):
def __init__(self):
Oyun.__init__(self)
self.ego = 0
def goster(self):
Oyun.goster(self)
print "ego:", self.ego
def fabrikayik(self,miktar):
macera.fabrika = macera.fabrika - miktar
self.ego = self.ego + 2
print "Tebrikler. Oyuncunun", miktar, \
"adet fabrikasn yktnz!"
print "stelik egonuz da byd!"
dsman = Dusman()
11.2. Snflar
207
208
self.fabrika = 4
self.isci = 10
def goster(self):
print "enerji:", self.enerji
print "para:", self.para
print "fabrika:", self.fabrika
print "i
si:", self.isci
oyun = Oyun()
class Oyuncu(Oyun):
def __init__(self):
Oyun.__init__(self)
def fabrikakur(self,miktar):
if self.enerji > 3 and self.para > 10:
self.fabrika = miktar + self.fabrika
self.enerji = self.enerji - 3
self.para = self.para - 10
print miktar, "adet fabrika kurdunuz! Tebrikler!"
else:
print "Yeni fabrika kuramazsnz. \
Yeterli enerjiniz/paranz yok!"
oyuncu = Oyuncu()
class Dusman(Oyun):
def __init__(self):
Oyun.__init__(self)
self.ego = 0
def goster(self):
Oyun.goster(self)
print "ego:", self.ego
def fabrikayik(self,miktar):
oyuncu.fabrika = oyuncu.fabrika - miktar
self.ego = self.ego + 2
print "Tebrikler. Oyuncunun", miktar, \
"adet fabrikasn yktnz!"
print "stelik egonuz da byd!"
dusman = Dusman()
Bu kodlar hakknda son bir noktaya daha deginelim. Hatrlarsanz oyuna baslarken olusturulan
niteliklerde degisiklik yapabiliyorduk. Mesela yukarda Dusman snf iin ego adl yeni
bir nitelik tanmlamstk. Bu nitelik sadece Dusman tarafndan kullanlabiliyordu, Oyuncu
tarafndan degil. Ayn sekilde, yeni bir nitelik belirlemek yerine, istersek varolan bir niteligi
iptal de edebiliriz. Diyelim ki Oyuncunun oyuna baslarken fabrikalar olsun istiyoruz, ama
Dusmann oyun baslangcnda fabrikas olsun istemiyoruz. Bunu syle yapabiliriz:
11.2. Snflar
209
class Dusman(Oyun):
def __init__(self):
Oyun.__init__(self)
del self.fabrika
self.ego = 0
Grdgnz gibi Dusman snf iin __init__ fonksiyonunu tanmlarken fabrika niteligini
del komutuyla siliyoruz. Bu silme islemi sadece Dusman snf iin geerli oluyor. Bu islem
teki snflar etkilemiyor. Bunu syle de ifade edebiliriz:
del komutu yardmyla fabrika adl degiskene Dusman adl blgeden erisilmesini
engelliyoruz.
Dolaysyla bu degisiklik sadece o blgeyi etkiliyor. teki snflar ve daha sonra
olusturulacak yeni snflar bu islemden etkilenmez. Yani aslnda del komutuyla herhangi bir
seyi sildigimiz yok! Sadece erisimi engelliyoruz.
Kk bir not: Burada blge olarak bahsettigimiz sey aslnda Pythoncada isim alan
(namespace) olarak adlandrlyor.
Simdi
Bu rnek gayet dzgn alssa da bu snf daha dzgn ve dzenli bir hale getirmemiz
mmkn:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
class Arayuz(Frame):
def __init__(self):
Frame.__init__(self)
self.pack()
self.pencerearaclari()
210
def pencerearaclari(self):
self.dugme = Button(self, text="tamam", command=self.yaz)
self.dugme.pack()
def yaz(self):
print "Gr
smek zere!"
uygulama = Arayuz()
uygulama.mainloop()
Burada dikkat ederseniz, Tkinterin Frame adl snfn miras aldk. Buradan anlayacagmz
gibi, miras alma (inheritance) zelligini kullanmak iin miras alacagmz snfn o anda
kullandgmz modl iinde olmas sart degil. Burada oldugu gibi, baska modllerin iindeki
snflar da miras alabiliyoruz. Yukardaki kodlar dikkatlice inceleyin. Basta biraz karsk gibi
grnse de aslnda daha nce verdigimiz basit rneklerden hi bir fark yoktur.
Grdgnz gibi, eski tip snflarda baska bir snf miras alma zorunlulugu yoktur. O yzden
snflar istersek parantezsiz olarak tanmlayabiliyoruz. Yeni tip snflarda ise her snf mutlaka
baska bir snf miras almaldr. Eger kodlarnz iinde gerekten miras almanz gereken baska
bir snf yoksa, ntanml olarak object adl snf miras almanz gerekiyor. Dolaysyla
politikamz su olacak:
Ya bir snf miras al, ya da miras alman gereken herhangi bir snf yoksa, object adl snf
miras al...
Dedigimiz gibi, eski ve yeni snflar arasndaki en temel fark budur.
Aslnda daha en basta hi eski tip snflar anlatmadan dogrudan yeni tip snflar anlatmakla
ise baslayabilirdik. Ama bu pek dogru bir yntem olmazd. nk her ne kadar eski tip
snflar sonraki bir Python srmnde tedavlden kaldrlacaksa da, etrafta eski snflarla
yazlms bolca kod greceksiniz. Dolaysyla sadece yeni tip snflar grenmek mevcut
tabloyu eksik alglamak olacaktr...
211
Yukarda hatrlarsanz pass ifadesini kullanmstk. Snflarn yaps geregi bir kod blogu
belirtmemiz gerektiginde, ama o anda yazacak bir seyimiz olmadgnda srf bir yer tutucu
vazifesi grsn diye o pass ifadesini kullanmstk. Yine bu pass ifadesini kullanarak baska bir
sey daha yapabiliriz. Su
rnege bakalm:
class BosSinif(object):
pass
Bylece ii bos da olsa kurallara uygun bir snf tanmlams olduk. Ayrca dikkat ederseniz,
snfmz tanmlarken yeni snf yapsn kullandk. zel olarak miras alacagmz bir snf
olmadg iin dogrudan object adl snf miras aldk. Yine dikkat ederseniz snfmz iin bir
rnek (instance) de belirtmedik. Hem snfn iini doldurma isini, hem de rnek belirleme isini
komut satrndan halledecegiz. nce snfmz rnekliyoruz:
sinifimiz = BosSinif()
sinifimiz.sayi1 = 45
sinifimiz.sayi2 = 55
sinifimiz.sonuc = sinifimiz.sayi1 * sinifimiz.sayi2
sinifimiz.sonuc
2475
Istersek snfmzn son halini, Python snflarnn __dict__ metodu yardmyla grebiliriz:
sinifimiz.__dict__
{'sayi2': 55, 'sayi1': 45, 'sonuc': 2475}
Grdgnz gibi snfn ierigi aslnda bir szlkten ibaret... Dolaysyla szlklere ait su
islemler snfmz iin de geerlidir:
sinifimiz.__dict__.keys()
['sayi2', 'sayi1', 'sonuc']
sinifimiz.__dict__.values()
[55, 45, 2475]
Buradan grendigimiz baska bir sey de, snflarn ieriginin dinamik olarak
degistirilebilecegidir. Yani bir snf her seyiyle tanmladktan sonra, istersek o snfn
niteliklerini etkilesimli olarak degistirebiliyoruz.
212
11.4 Sonu
Bylece Nesne Tabanl Programlama konusunun sonuna gelmis oluyoruz. Aslnda daha
dogru bir ifadeyle, Nesne Tabanl Programlamaya hzl bir giris yapms oluyoruz. nk
NTP su birka sayfada anlatlanlardan ibaret degildir. Bu yazmzda bizim yapmaya
alstgmz sey, okuyucuya NTP hakknda bir fikir vermektir. Eger okuyucu bu yaz
sayesinde NTP hakknda hi degilse birazck fikir sahibi olmussa kendimizi basarl
sayacagz. Bu yazdaki ama NTP gibi etrefilli bir konuyu okuyucunun gznde bir nebze de
olsa sevimli klabilmek, konuyu kolay hazmedilir bir hale getirmektir. Okuyucu bu yazdan
sonra NTPye iliskin baska kaynaklar daha bir kendine gvenle inceleme imknna
kavusacak ve okudugunu daha kolay anlayacaktr.
11.4. Sonu
213
BLM 12
12.1 Giris
Orada burada mutlaka Pythonun varsaylan kod zcsnn ascii olduguna dair bir cmle
duymussunuzdur. Yine sagda solda Pythonun unicodeyi destekledigine dair bir cmle de
duymus olmalsnz. O halde bu ascii ve unicode denen seylerin ne oldugunu da merak
etmissinizdir.
Simdi
size burada isin teknik ksmna bulasmadan hem ascii, hem de unicode ile ilgili ok
kaba bir tarif verecegim:
ascii, Trkeye zg s, , , g, ve gibi harfleri tanmayan bir karakter
kodlama biimidir.
unicode ise Trkeye zg harflerle birlikte dnya zerindeki pek ok dile ait harfleri de
tanyabilen karakter kodlama biimlerini ieren, gelismis bir sistemdir.
Esasnda unicode, karakter kodlarn gsteren byk bir listeden ibarettir. Bu liste iinde
dnyadaki (hemen hemen) btn dillere ait karakterler, simgeler, harfler, vb. yer alr. Ayn
sekilde ascii de karakter kodlarn ieren bir listedir. Ancak ascii listesi sadece 128
karakterden olusurken, unicode yz binlerce karakteri temsil edebilir.
Iste biz bu makalede, her yerde karsmza kan bu ascii ve unicode kavramlarn anlamaya, bu
kavramlarn Pythondaki yerini ve Pythonda ne sekilde kullanldgn grenmeye alsacagz.
nce asciiden baslayalm...
12.2 ascii
Ne kadar gelismis olurlarsa olsunlar, bugn kullandgmz bilgisayarlarn anladg tek sey
saylardr. Yani mesela karakter, harf ve kelime gibi kavramlar bir bilgisayar iin hibir sey
ifade etmez. rnegin ekranda grdgmz a harfi znde sadece bir saydan ibarettir.
Bilgisayar bunu a harfi seklinde degil, bir say olarak grr. Dolaysyla, ekranda
grdgmz btn harfler ve simgeler makine dilinde bir say ile temsil edilir. Iste bu her
karakteri bir sayyla temsil etme islemine karakter kodlama (character encoding) ad verilir.
Her bir karakter bir sayya karslk gelecek sekilde, bu karakterleri ve bunlarn karslg olan
214
saylar bir araya toplayan sistematik yapya ise karakter kmesi (charset character set)
denir. rnegin ascii, unicode, ISO-8859, vb. birer karakter kmesidir. nk bunlar her biri
bir sayya karslk gelen karakterleri bir arada sunan sistematik yaplardr. Biraz sonra bu
sistemleri daha detayl bir sekilde inceledigimizde tam olarak ne demek istedigimizi gayet net
anlayacaksnz.
1960l yllara gelininceye kadar, yaz yazmaya yarayan makineler reten her firma, farkl
karakterlerin farkl saylarla temsil edildigi karakter kmeleri kullanyordu. Bu karmasklgn
bir sonucu olarak, herhangi bir makinede olusturulan bir metin baska bir makinede ayn
sekilde grntlenemiyordu. nk rnegin a harfi bir makinede falanca say ile temsil
edilirken, baska bir makinede filanca say ile temsil ediliyordu. Hatta ayn reticinin farkl
model makinelerinde dahi bir btnlk saglanms degildi... Dolaysyla her retici kendi
ihtiyalarna uygun olarak farkl bir karakter kmesi kullanyordu.
Bu dagnklg nlemek ve yaz makinelerinde bir birlik saglamak iin American Standards
Association (Amerikan Standartlar Birligi) tarafndan American Standard Code for
Information Interchange (Bilgi Alsverisi iin Amerikan Standart Kodu) ad altnda bir
standartlasma alsmas yrtlmesine karar verildi. Iste ascii bu American Standard Code
for Information Interchange ifadesinin ksaltmasdr. Bu kelime askii seklinde telaffuz
edilir...
Ilk srm 1963 ylnda yaymlanan ascii 7-bitlik bir karakter kmesidir. Dolaysyla bu kme
iinde toplam 27 = 128 adet karakter yer alabilir, yani bu sistemle sadece 128 adet karakter
kodlanabilir (eger 7-bit kavram size yabanc ise okumaya devam edin. Biraz sonra bu
kavram aklayacagz).
Bu bahsettigimiz 128 karakteri ieren ascii tablosuna (yani ascii karakter kmesine)
http://www.asciitable.com/ adresinden erisebilirsiniz. Buradaki tablodan da greceginiz gibi,
toplam 128 saynn (0dan baslayarak) ilk 33 tanesi ekranda grnmeyen karakterlere
ayrlmstr. Bu ilk 33 say, bir metnin aksn belirleyen sekme, yeni satr ve benzeri
karakterleri temsil eder. Ayrca grdgnz gibi, karakter kmesi denen sey, temelde belli
karakterlerle belli saylar eslestiren bir tablodan ibarettir...
Mesela ascii tablosunda 10 saysnn yeni satr karakterini temsil ettigini gryoruz (O
tabloda dec stununa bakn). ascii tablosu bugn iin de geerlidir. Bu yzden bu tablodaki
karakterleri modern sistemler de kabul edecektir. Mesela Pythonda, chr() fonksiyonundan da
yararlanarak syle bir sey yazabiliriz:
>>> print "Merhaba" + chr(10) + "dnya"
Merhaba
dnya
Grdgnz gibi, gerekten de 10 says yeni bir satra gememizi saglad. Burada chr()
fonksiyonu ascii tablosundaki saylarn karakter karslklarn grmemizi ve kullanabilmemizi
saglyor...
Ayn tabloda 9 saysnn ise sekme karakterini temsil ettigini gryoruz. Bu da bize
Pythonda syle bir sey yazma olanag saglyor:
>>> print "Merhaba" + chr(9) + "dnya"
12.2. ascii
215
Merhaba dnya
Yukarda yazdgmz kodlar isleten Python, Merhaba ve dnya kelimeleri arasnda bir
sekmelik bosluk brakt. Eger buradaki sekme boslugunun az oldugunu dsnyorsanz
kodunuzu syle de yazabilirsiniz:
>>> print "Merhaba" + chr(9) * 2 + "dnya"
Merhaba
dnya
chr(9)a karslk gelen sekme karakterini istediginiz kadar tekrar ederek, karakter dizileri
arasnda istediginiz boyutta sekmeler olusturabilirsiniz. Elbette bunu Pythonda \t kas
dizisini kullanarak da yapabileceginizi biliyorsunuz.
Eger ascii sisteminden yararlanp bilgisayarnzn bir bip sesi karmasn isterseniz sadece
syle bir sey yazmanz yeterli olacaktr:
>>> print chr(7)
!bip!
Ancak bu biplemeyi (eger kernel modllerinden biri olan pcspkr ykl degilse) GNU/Linux
sistemlerinde duyamayabilirsiniz.
Elbette ascii tablosu sadece yukardaki grnmez karakterlerden ibaret degildir. Tablodan
grdgmz gibi, 33ten 128e kadar olan ksmda ekrana baslabilen karakterler yer alyor.
Mesela a harfi 97 says ile gsteriliyor. Dolaysyla Pythonda syle bir sey yazabiliyoruz:
>>> print "Merhab" + chr(97) + "dnya"
Merhabadnya
Burada iki kelime arasnda tabii ki bosluk yer almyor. Bosluk karakterini kendiniz
yerlestirebilirsiniz. Ama eger ascii kodlarn dogrudan karakter dizilerinin iinde kullanmak
isterseniz, ascii tablosunda dec stunu yerine oct stunundaki saylar da kullanabilirsiniz.
Tablodaki oct stununu kontrol ettigimizde a harfinin 141 saysna karslk geldigini
gryoruz. O halde syle bir kod yazmamz mmkn:
>>> print "Merhab\141 dnya"
Merhaba dnya
Burada 141 saysn dogrudan kullanmadgmza dikkat edin. Pythonun ekrana 141
yazdrmak istedigimizi zannetmemesi iin \ kas dizisini kullanarak, Pythona o 141
bildigin 141 degil, gibi bir mesaj vermis oluyoruz.
Yok, ben illa dec stunundaki ondalk saylar kullanmak istiyorum! diyorsanz sizi
kracak degiliz. Bunu elbette su sekilde yapabileceginizi biliyorsunuz:
>>> print "Merhab%s dnya" %chr(97)
Dikkat ederseniz, ascii tablosunda Hx (Hexadecimal) adl bir stun daha var. Eger bu
stundaki saylar size daha sevimli geliyorsa syle bir yazm tarz benimseyebilirsiniz:
216
ascii tablosunu incelediginizde, bu tabloda baz seylerin eksik oldugu gznze arpms
olmal. Mesela bu tabloda sg gibi harfleri gremiyoruz...
Simdi
Eger bu kodlar dogrudan etkilesimli kabuk zerinde alstrmssanz Python size dzgn bir
kt vermis olabilir. Ancak bu sizi yanltmasn. Etkilesimli kabuk pratik bir aratr, ama her
zaman gvenilir bir ara oldugu sylenemez. Burada aldgnz ktlarn her ortamda ayn
kty vereceginden emin olamazsnz. O yzden asl programlarnzda dogrudan yukardaki
gibi bir kod yazamazsnz.
Bu kodu bir metin dosyasna yazp kaydettikten sonra program alstrmak istedigimizde
syle bir kt alrz:
SyntaxError: Non-ascii character '\\xfc' in file
deneme.py on line 1, but noencoding declared; see
http://www.python.org/peps/pep-0263.html for details
Demek ki Pythondaki varsaylan kodlama biimi hakikaten ascii imis... Yukardaki durum
nedeniyle, Python ascii tablosunda yer almayan bir karakterle karslastg zaman dogal olarak
hata mesajnda grdgmz kty veriyor.
Bu arada, asciinin 7-bitlik bir sistem oldugunu sylemistik. Peki 7-bitlik ne demek?
Hemen ksaca onu da aklayalm:
Bildiginiz gibi bilgisayarlarn temelinde 1ler ve 0lar yatar. Bilgisayarlar yalnzca bu saylar
anlayp bu saylarla islem yapabilir. Bu 1 ve 0larn her birine bit ad verilir. Bu 1 ve 0larn
7 tanesi yan yana gelince 7-bitlik bir say olusur!
Gayet mantkl, degil mi?
Iste ascii sisteminde tanmlanan btn karakterler 7-bitlik bir say iine sgdrlabiliyor. Yani 7
adet 1 ve 0 btn ascii karakterleri temsil etmeye yetiyor. Mesela F harfinin ascii karslg
olan 70 says ondalk bir saydr. Bu ondalk say ikili dzende 1000110 saysna karslk
12.2. ascii
217
gelir. Pythonda herhangi bir ondalk saynn ikili dzende hangi sayya karslk geldigini
bulmak iin bin() adl fonksiyondan yararlanabilirsiniz:
>>> bin(70)
'0b1000110'
Bu saynn basndaki 0b karakterleri Pythonun ikili saylar gstermek iin kullandg bir
aratr. Bu ara Pythona bir seyler ifade ediyor olabilir, ama bize bir sey ifade etmez. O
yzden bu sayda bizi ilgilendiren ksm 1000110.
Grdgnz gibi burada toplam 7 adet 1 ve 0 var... Baska bir rnek verelim: ascii tablosunda
r harfi 114 saysna karslk geliyor. Bu ondalk saynn ikili dzendeki karslg 1110010
saysdr:
>>> bin(114)
'0b1110010'
Yine grdgnz gibi, bu ikili say da 7 adet 1 ve 0dan olusuyor. Dolaysyla bu da 7-bitlik
bir saydr. 7-bitle gsterilebilecek son say 127dir. Bunun da ikili dzendeki karslg
1111111 saysdr. 128 says ikili dzende 10000000 olarak gsterilir. Grdgnz gibi
128in ikili dzendeki karslg olan say 7-bit degil. nk burada 7 adet 1 ve 0 yerine 8 adet
1 ve 0 var... Dolaysyla 7 bit kullanarak 0 says ile birlikte 128 adet ondalk sayy
gsterebiliyoruz. 129. say ancak 8 bit kullanlarak gsterilebiliyor.
1990l yllarn ortalarna kadar bilgisayar sistemleri sadece bu 7-bitlik veriler ile islem
yapyordu. Ancak 90lu yllarn ortalarndan itibaren btn bilgisayar sistemleri 8 bitlik
verileri de depolayabilmeye baslad. 8. bitin gelisiyle birlikte, 7-bitlik sistemin sundugu 128
karaktere ek olarak bir 128 karakteri daha temsil edebilme olanag dogdu. nk 8-bitlik
sistemler 28 = 256 adet karakterin kodlanmasna imkn tanr.
128 karakteri destekleyen standart asciinin Ingilizce dsndaki karakterleri gsterememesi ve
8. bitin sagladg olanaklar gz nnde bulundurularak ortaya Genisletilmis ascii diye bir
sey kt. Ancak ilk 128 karakterden sonra gelen 128 karakterin hangi karakterleri temsil
edecegi konusu, yani Genisletilmis ascii denen sistem standart bir yapya hi bir zaman
kavusamad. Bilgisayar reticileri bu 8. biti kendi ihtiyalarna gre doldurma yolunu setiler.
Bylece ortaya kod sayfas (codepage) denen bir kavram kt.
zellikle IBM ve Microsoft gibi byk sirketlerin, kendi ihtiyalarna ve farkl lkelere gre
dzenlenmis farkl farkl kod sayfalar bulunur. rnegin Microsoft firmasnn Trkiyeye
gnderdigi bilgisayarlarda kullandg, 857 numaral bir kod sayfas vardr. Bu kod sayfasna
http://msdn.microsoft.com/en-us/library/cc195068.aspx adresinden ulasabilirsiniz. Bu
adresteki kod sayfasnda greceginiz gibi, saylar 32den baslyor. ascii tablosunun ilk 32
says ekranda grnmeyen karakterleri temsil ettigi iin Microsoft bunlar gsterme geregi
duymams. Bu tabloda 128e kadar olan ksm zaten standart asciidir ve btn kod
sayfalarnda ilk 128lik ksm ayndr. Sonraki 128lik ksm ise farkl kod sayfalarnda farkl
karakterlere karslk gelir. rnegin buradaki 857 numaral kod sayfasnda ikinci 128lik ksm
zel karakterlere ayrlmstr. Bu kod sayfas Trkedeki karakterleri dzgn gsterebilmek
iin retildiginden bu listede s, , , g, ve I gibi harfleri grebiliyoruz. Ama
eger http://msdn.microsoft.com/en-us/library/cc195065.aspx adresindeki 851 numaral kod
sayfasna bakacak olursanz, bu listede ikinci 128lik ksmn 857 numaral kod
218
Burada ord() kts 135 sonucunu veriyor. 135 saysna karslk gelen karakter standart
asciinin dsnda kaldg iin bu say farkl karakter kmelerinde farkl karakterlerle gsterilir.
nk dedigimiz gibi standart ascii sadece 128 karakterden olusur. Dolaysyla karakteri
ikinci 128lik ksmda yer alr. Bildiginiz gibi, ikinci 128lik ksmda yer alan karakterler
btn karakter kmelerinde ayn degil. Yukardaki komutlar 857 numaral kod sayfasn
kullanan bir Windows isletim sisteminde verildi. rnegin bu kod sayfasnda Trke
karakterler su saylara karslk geliyor:
>>> for i in '
s
g
I':
...
print i, ord(i)
s 159
135
148
g 167
12.2. ascii
219
129
141
I 152
231
246
g 240
252
253
I 221
12.3 unicode
Her ne kadar ascii kodlama sistemi Ingilizce dsndaki karakterleri temsil etmek konusunda
yetersiz kalsa da insanlar uzun sre asciiyi temel alarak alstlar. Yerel ihtiyalar gidermek
iin ise 8. bitin sagladg 128 karakterlik alandan ve reticilerin kendi kod sayfalarndan
220
yararlanld. Ancak bu yaklasmn yetersizligi gn gibi ortadadr. Bir defa 7 bit bir kenara, 8
bit dahi dnya zerindeki btn dillerin karakter ve simgelerini gstermeye yetmez. rnegin
Asya dillerinin alfabelerindeki harf saysn temsil etmek iin 256 karakterlik alan kesinlikle
yetmeyecektir ve yetmemistir de... Ayrca mesela tek bir metin iinde hem Trke hem de
Yunanca karakterler kullanmak isterseniz ascii sizi yar yolda brakacaktr. Trke iin 857
numaral kod sayfasn (veya iso-8859-9 karakter kmesini) kullanabilirsiniz. Ama bu kod
sayfasnda Yunanca harfler yer almaz... Onun iin 851 numaral kod sayfasn veya iso-8859-7
karakter kmesini kullanmanz gerekir. Ancak bu iki kod sayfasn ayn metin iinde
kullanmanz mmkn degil.
Iste btn bu yetersizlikler evrensel bir karakter kmesi olusturmann gerekliligini ortaya
kard. 1987 ylnda Xerox firmasndan Joseph D. Becker ve Lee Collins ile Apple
firmasndan Mark Davis byle bir evrensel karakter kmesi olusturabilmenin altyaps
zerinde alsmaya baslad. unicode kelimesini ortaya atan kisi Joe Beckerdir. Becker bu
kelimeyi benzersiz (unique), birlesik (unified) ve evrensel (universal) bir kodlama biimi
anlamnda kullanmstr.
Joseph Beckerin 29 Agustos 1988 tarihinde yazdg Unicode 88 baslkl makale, unicode
hakkndaki ilk taslak metin olmas bakmndan nem tasr. Becker bu makalede neden
unicode gibi bir sisteme ihtiya duyuldugunu, asciinin Ingilizce dsndaki dillere ait
karakterleri gstermekteki yetersizligini ve herkesin ihtiyacna cevap verebilecek bir sistemin
nasl ortaya karlabilecegini anlatr. Bu makaleye http://unicode.org/history/unicode88.pdf
adresinden ulasabilirsiniz.
1987 ylndan itibaren unicode zerine yaplan yogun alsmalarn ardndan 1991 ylnda hem
Unicode Konsorsiyum kurulmus hem de ilk unicode standard yaymlanmstr. Unicode ve
bunun tarihi konusunda en ayrntl bilgiyi http://www.unicode.org/ adresinden
edinebilirsiniz...
Ilk unicode standard 16-bit temel alnarak hazrlanmstr. Unicode kavram ilk ortaya
ktgnda Joe Becker 16 bitin dnyadaki btn dillere ait karakterleri temsil etmeye
yetecegini dsnyordu. Ne de olsa;
27 = 128
28 = 256
216 = 65536
Ancak zamanla 16 bitin dahi tm dilleri kapsayamayacag anlasld. Bunun zerine unicode
2.0dan itibaren 16-bit snrlamas kaldrlarak, dnya zerinde konusulan dillere ilaveten
arkaik dillerdeki karakterler de temsil edilebilme olanagna kavustu. Dolaysyla unicode
16-bitlik bir sistemdir, yargs dogru degildir. Unicode ilk ktgnda 16-bitlikti, ama artk
byle bir snrlama yok...
Unicode, asciiye gre farkl bir baks asna sahiptir. asciide sistem olduka basittir. Buna
gre her say bir karaktere karslk gelir. Ancak unicode iin ayn seyi sylemek mmkn
degil. Unicode sisteminde karakterler yerine kod konumlar (code points) bulunur. O yzden
unicode sisteminde baytlar zerinden dsnmek yanltc olacaktr.
rnegin http://www.unicode.org/charts/PDF/U0100.pdf adresindeki Latin Extended A adl
unicode tablosuna bakalm. Bu tablo Trke ve Azericenin de dhil oldugu baz dillere zg
12.3. unicode
221
karakterleri barndrr. Bu sayfada yer alan tabloda her karakterin bir kod konumu
bulundugunu gryoruz. Mesela g harfinin kod konumu 011Fdir. Unicode dilinde kod
konumlar geleneksel olarak U+xxxx seklinde gsterilir. Mesela g harfinin kod konumu
U+011Fdir. Esasnda bu 011F bir onaltlk saydr. Bunun ondalk say olarak karslgn
bulmak iin int() fonksiyonundan yararlanabilirsiniz:
>>> int("011F", 16)
287
Pythonda chr() fonksiyonuna ok benzeyen unichr() adl baska bir fonksiyon daha bulunur.
chr() fonksiyonu bir saynn ascii tablosunda hangi karaktere karslk geldigini gsteriyordu.
unichr() fonksiyonu ise bir saynn unicode tablosunda hangi kod konumuna karslk geldigini
gsterir. Mesela yukarda grdgmz 287 saysnn hangi kod konumuna karslk geldigine
bakalm:
>>> unichr(287)
u'\u011f'
Grdgnz gibi g harfinin kod konumu olan 011Fyi elde ettik. Burada Python kendi i
isleyisi asndan 011Fyi u\u011F seklinde gsteriyor. Yukardaki kodu syle yazarak
dogrudan g harfini elde edebilirsiniz:
>>> print unichr(287)
'
g'
Peki, dogrudan bir say vererek degil de, karakter vererek o karakterin unicode kod konumunu
bulmak mmkn m? Elbette. Bunun iin yine ord() fonksiyonundan yararlanabiliriz:
>>> ord(u"
g")
287
ord() fonksiyonu bir karakterin kod konumunu ondalk say olarak verecektir. Elde ettiginiz bu
ondalk sayy unichr() fonksiyonuna vererek onaltlk halini ve dolaysyla unicode kod
konumunu elde edebilirsiniz:
>>> unichr(287)
u'\u011f'
Bu arada ord() fonksiyonunu burada nasl kullandgmza dikkat edin. Sadece ord(g)
yazmak Pythonun hata vermesine sebep olacaktr. nk znde ord() fonksiyonu sadece
0-256 aralgndaki ascii karakterlerle alsr. Eger yukardaki kodu ord(g) seklinde
yazarsanz, syle bir hata alrsnz:
>>> ord("
g")
ValueError: chr() arg not in range(256)
gnin degeri 287 oldugu ve bu say da 256dan byk oldugu iin ord() fonksiyonu normal
olarak bu karakteri gsteremeyecektir. Ama eger siz bu kodu ord(ug) seklinde basna bir u
222
harfi getirerek yaparsanz mutlu mesut yasamaya devam edebilirsiniz... Biraz sonra bu u
harfinin tam olarak ne ise yaradgn grecegiz. Simdilik
Demek ki harfinin unicode kod konumu 305 imis... Ancak bildiginiz gibi bu ondalk bir
degerdir. Unicode kod konumlar ise onaltlk sisteme gre gsterilir. O halde kodumuzu
yazalm:
>>> unichr(305)
u'\u0131'
Burada Pythonun kendi ekledigi u\u ksmn atarsak 0131 saysn elde ederiz. Test
etmek amacyla bu 0131 saysnn ondalk karslgn kontrol edebileceginizi biliyorsunuz:
>>> int("0131", 16)
305
Simdi
Unicode sistemi bu kod konumlarndan olusan devasa bir tablodur. Unicode tablosuna
http://www.unicode.org/charts adresinden ulasabilirsiniz. Ancak unicode sadece bu kod
konumlarndan ibaret bir sistem degildir. Zaten unicode sistemi sadece bu kod konumlarndan
ibaret olsayd pek bir ise yaramazd. nk unicode sistemindeki kod konumlarnn
bilgisayarlarda dogrudan depolanmas mmkn degildir. Bilgisayarlarn bu kod konumlarn
isleyebilmesi iin bunlarn bayt olarak temsil edilebilmesi gerekir. Iste unicode denen sistem
bir de bu kod konumlarn bilgisayarlarn isleyebilmesi iin bayta eviren kod zclere
sahiptir.
Unicode sistemi iinde UTF-8, UTF-16 ve UTF-32 gibi kod zcler vardr. Bunlar arasnda
en yaygn kullanlan UTF-8dir ve bu kodlama sistemi GNU/Linux sistemlerinde de standart
olarak kabul edilir. Python programlama dili de 3.x srmlerinden itibaren varsaylan
kodlama biimi olarak UTF-8i kullanr. Hemen bunu teyit edelim.
Python 3.x srmnde syle bir komut verelim:
>>> import sys
>>> sys.getdefaultencoding()
12.3. unicode
223
'utf-8'
Yukarda da gsterdigimiz gibi, Pythonun 2.x srmlerinde bu komutun kts ascii idi...
Kod zcler her kod konumunu alp farkl bir biimde kodlarlar. Ufak bir rnek yapalm:
>>> unicode.encode(u"
g", "utf-8")
'\xc4\x9f'
>>> unicode.encode(u"
g", "utf-16")
'\xff\xfe\x1f\x01'
>>> unicode.encode(u"
g", "utf-32")
'\xff\xfe\x00\x00\x1f\x01\x00\x00'
Ancak daha nce syledigimiz seyler para para bilgiler ieriyordu. Bu blmde ise gerek
hayatta unicode ve Pythonu nasl bagdastracagmz anlamaya alsacagz.
Pythonda karakterlere iliskin iki farkl tip bulunur: karakter dizileri (strings) ve unicode
dizileri (unicode strings). Mesela su bir karakter dizisidir:
>>> "elma"
Su
ise bir unicode dizisidir:
224
>>> u"elma"
Grdgnz gibi, unicode dizileri, karakter dizilerinin basna bir u harfi getirilerek kolayca
elde edilebiliyor.
Peki, bir karakter dizisini unicode olarak tanmlamann bize ne faydas var? Bir rnek bin sze
bedeldir... O yzden isterseniz derdimizi bir rnekle anlatmaya alsalm. Suna
bir bakn:
>>> kardiz = "
sk"
>>> print kardiz.upper()
sK
Grdgnz gibi, upper() metodu, ascii olmayan karakterler ieren sk kelimesini dzgn
bir sekilde bytemedi. Bu sorunun stesinden gelebilmek iin, ascii olmayan karakterler
ieren karakter dizilerini unicode olarak tanmlamamz gerekir:
>>> kardiz = u"
sk"
>>> print kardiz.upper()
I
SIK
Dedik ki, eger bu satr bir metin dosyasna yazp kaydeder ve ardndan bu program
alstrrsanz syle bir hata mesaj alrsnz:
SyntaxError: Non-ascii character '\\xfc' in file
deneme.py on line 1, but no encoding declared; see
http://www.python.org/peps/pep-0263.html for details
Hatrlarsanz, unicode konusundan sz ederken unicode sistemi iinde baz kod zclerin
yer aldgn sylemistik. Orada da dedigimiz gibi, utf-8 de bu kod zclerden biri ve en
gzde olandr. Yukardaki satr yardmyla, yazdgmz programn utf-8 ile kodlanmasn
225
Yazacagnz betiklerin en basna yukardaki gibi bir satr koyarak, programlarnza unicode
destegi vermis oluyorsunuz. Yazdgnz o satr sayesinde Python kendi varsaylan kod
zcs olan asciiyi kullanarak programnzn kmesine sebep olmak yerine, sizin
belirlediginiz kod zc olan utf-8i (veya cp-1254) kullanarak programlarnzn iinde
rahatlkla Ingilizce dsndaki karakterleri de kullanmanza msaade edecektir.
Hatrlarsanz, unicode sistemleri iindeki kod konumlarnn bilgisayarlar asndan pek bir sey
ifade etmedigini, bunlarn bilgisayarlarda depolanabilmesi iin ncelikle uygun bir kod
zc yardm ile bilgisayarn anlayabilecegi baytlara dnstrlmesi gerektigini
sylemistik. Isterseniz biraz da bunun ne demek oldugunu anlamamza yardmc olacak birka
rnek yapalm.
Biliyoruz ki, Pythonda unicode dizileri olusturmann en kolay yolu, karakter dizilerinin
basna bir adet u harfi eklemektir:
>>> uni_diz = u"
sk"
Bu unicode dizisini etkilesimli kabukta yazdrdgmz zaman syle bir kt elde ediyoruz:
>>> uni_diz
u'\u0131\u015f\u0131k'
Burada grdgmz sey bir dizi unicode kod konumudur... Dolaysyla bu unicode dizisi bu
haliyle bilgisayarda depolanamaz. Isterseniz deneyelim:
>>> f = open("deneme.txt", "w")
>>> f.write(uni_diz)
Python, unicode kod konumlarndan olusmus bir diziyi bilgisayara kaydetmek istedigimizde
olanca iyi niyetiyle bu kod konumlarn bilgisayarn anlayabilecegi bir biime dnstrmeye
alsr. Bunu yaparken de tabii ki varsaylan kod zcs olan asciiyi kullanmay dener.
Eger uni_diz adl degiskende sadece Ingilizce karakterler olsayd, Python bunlar ascii
yardmyla bilgisayarn anlayabilecegi bir biime evirir ve rahatlkla dosyaya yazdrabilirdi.
Ancak burada bulunan Trke karakterler nedeniyle ascii kod zcs bu karakterleri
zemez ve programn kmesine yol aar... Bu yzden bizim yapmamz gereken sey,
unicode dizilerini depolayabilmek iin ncelikle bunlar uygun bir kod zc yardmyla
bilgisayarn anlayabilecegi bir biime getirmektir. Biraz sonra bunu nasl yapacagmz
grecegiz. Ama biz simdilik yine yolumuza devam edelim.
226
ascii, unicode ve bunlarn Pythonla iliskisi konusunda temel bilgileri edindigimize gre
Pythondaki unicode desteginin biraz daha derinlerine inmeye baslayabiliriz. Bunun iin
isterseniz ncelikle unicode ile ilgili metotlara bir gz atalm.
Burada dikkat etmemiz gereken nemli bir nokta var. unicode() adl fonksiyon ikinci (ve hatta
nc) bir parametre daha alr. nce ikinci parametrenin ne olduguna bakalm:
>>> unicode("elma", "utf-8")
Burada elma adl karakter dizisini utf-8 adl kod zcy kullanarak bir unicode dizisi
haline getirdik. asciinin kendisi unicode sistemi iinde yer almasa da, ascii tablosunda
bulunan karakterler unicode sisteminde de ayn sekilde yer aldg iin, burada kullandgmz
unicode() fonksiyonu bir karakter dizisini ascii ile kodlamamza da msaade eder:
>>> unicode("elma", "ascii")
Peki karakter dizilerini bu sekilde kodlamak ne isimize yarar? Bunu anlamak iin syle bir
rnek verelim:
>>> a = "
srnga"
>>> print a.upper()
sRNGA
Grdgnz gibi, karakter dizilerinin metotlarndan biri olan upper(), iindeki Trke
karakterlerden tr srnga kelimesini bytemedi. Bu kelimeyi dzgn bir sekilde
bytebilmek iin iki yntem kullanabilirsiniz. nce basit olann grelim:
>>> a = u"
srnga"
>>> print a.upper()
SIRINGA
Burada daha en bastan srnga karakter dizisini unicode olarak tanmladk. Bu islemi,
karakter dizisinin basna sadece bir u harfi getirerek yaptk. Peki ya bastaki karakter dizisini
degistirme imknmz yoksa ne olacak? Iste bu durumda ikinci yolu tercih edebiliriz:
227
>>> a = "
srnga"
>>> b = unicode(a, "utf-8") #veya cp1254
>>> print b.upper()
SIRINGA
unicode() fonksiyonu karakterleri daha esnek bir biimde kodlamamz saglar. Eger burada
unicode() fonksiyonunu ikinci parametre olmadan agrrsanz hata mesaj alrsnz:
>>> b = unicode(a)
UnicodeDecodeError: 'ascii' codec can't decode
byte 0xc5 in position 0:ordinal not in range(128)
Daha nce de dedigimiz gibi, ikinci parametrenin belirtilmemesi durumunda Python ascii kod
zcsn kullanacaktr. O yzden, s ve harflerini dzgn grntleyebilmek iin
bizim utf-8 adl kod zcsn kullanmamz gerekiyor...
unicode() adl fonksiyon nc bir parametre daha alr. Bu parametre, kullanlan kod
zcnn, baz karakterleri dzgn kodlayamamas durumunda Pythonun ne yapmas
gerektigini belirler. Bu parametre farkl deger alr: strict, ignore ve replace. Hemen
bir rnek verelim:
>>> b = unicode(a, "ascii", errors = "strict")
UnicodeDecodeError: 'ascii' codec can't decode
byte 0xc5 in position 0:ordinal not in range(128)
Grdgnz gibi, biraz nce aldgmz hatann aynsn almamza sebep oldu bu kod... nk
errors adl parametrenin varsaylan degeri stricttir.
Peki, strict ne anlama geliyor? Eger errors adl parametreye deger olarak strict verirsek,
kullanlan kod zcnn dzgn kodlayamadg karakterlerle karslasldgnda Python bize
bir hata mesaj gsterecektir. Dedigimiz gibi, errorsun varsaylan degeri stricttir.
Dolaysyla eger errors parametresini hi kullanmazsanz, ters durumlarda Python size bir
hata mesaj gsterir. Bu parametre strict dsnda ignore ve replace adl iki deger daha
alabilir. nce ignorenin ne yaptgna bakalm:
>>> b = unicode(a, "ascii", errors = "ignore")
>>> print b.upper()
RNGA
Burada ignore degeri, Pythonun herhangi bir ters durumda, zlemeyen karakteri es
gemesini saglyor. Bu sebeple Python zlemeyen karakterleri tamamen ortadan
kaldryor... Peki replace degeri ne ise yaryor? Hemen bakalm:
>>> b = unicode(a, "ascii", errors = "replace")
>>> print b.upper()
????R??NGA
Bu anlattgmz konu ile ilgili olarak syle basit bir rnek verebiliriz:
# -*- coding: utf-8 -*a = raw_input("herhangi bir karakter yaznz: ")
print a.upper()
Eger kodlarmz bu sekilde yazarsak istedigimiz sonucu elde edemeyiz. Python ekranda
girdigimiz Trke karakterleri bu sekilde dzgn bytemeyecektir. Yukardaki kodlarn
alsmas iin syle bir sey yazmalyz:
# -*- coding: utf-8 -*a = raw_input("herhangi bir karakter yaznz: ")
print unicode(a, "utf-8", errors = "replace").upper()
veya:
# -*- coding: cp1254 -*a = raw_input("herhangi bir karakter yaznz: ")
print unicode(a, "cp1254", errors = "replace").upper()
Bylece unicodeye duyarl bir program yazms olduk. Artk kullanclarmz Ingiliz
alfabesindeki harflerin dsnda bir harf girdiklerinde de programmz dzgn alsacaktr.
Kullancnn, tannmayan bir karakter girmesi ihtimaline karslk da errors parametresine
replace degerini verdik...
Simdi
kardiz = "
sk"
unikod = unicode(kardiz, "utf-8")
f = open("deneme.txt", "w")
f.write(unikod)
229
Burada grdgmz sey bayt degil unicode kod konumlardr. unicode() fonksiyonu iinde
kullandgmz utf-8 zcsnn grevi ise sk kelimesini Pythonun dogru okumasn
saglamaktr...
Benzer bir seyi unicode() metodunu kullanarak daha da kolay bir sekilde yapabilirsiniz:
>>> unicode(u"
s")
u'\u015f'
Burada unicode() fonksiyonunu tek parametreyle kullandgmza dikkat edin. Eger utf-8 veya
baska bir kod zc kullanarak ikinci parametreyi de girersek Python burada bize bir hata
mesaj gsterecektir.
Tekrar tekrar syledigimiz gibi, bu kod konumu esasnda bilgisayarlar iin ok fazla sey ifade
etmez. Bunlarn bir sey ifade edebilmesi iin bir kod zc vastasyla kodlanmas gerekir.
Mesela bu kod konumunu utf-8 ile kodlamay tercih edebilirsiniz:
>>> kod_konumu = unicode(u"
s")
>>> utfsekiz = kod_konumu.encode("utf-8")
Iste Pythonda asl dnstrme islemlerini yapanlar bu encode() ve decode() adl metotlardr.
Dolaysyla artk syle bir sey yazabilirsiniz:
>>>
>>>
>>>
>>>
>>>
>>>
kardiz = "
sk"
unikod = unicode(kardiz, "utf-8")
unibayt = unicode.encode(unikod, "utf-8")
f = open("deneme.txt", "w")
f.write(unibayt)
f.close()
Pythonda karakterlere iliskin iki farkl tip bulunur: karakter dizileri ve unicode dizileri.
Mesela su bir karakter dizisidir:
>>> kardiz = "elma"
Su
da bir unicode dizisi:
>>> kardiz = u"elma"
Grdgnz gibi, Pythonda unicode dizisi olusturmak olduka kolay. Yapmamz gereken tek
sey karakter dizisinin basna bir u harfi getirmek.
Unicode dizileri birtakm kod konumlarndan meydana gelir. Bu kod konumlarnn bir ise
yarayabilmesi iin bunlarn uygun bir kod zc yardmyla bayta evrilmeleri gerekir.
Unicode sistemi iinde UTF-8, UTF-16 ve UTF-32 gibi kod zcler vardr. Bu kod
zclerin her biri, kod konumlarn farkl bir biimde ve boyutta bayta evirir. Bu kod
zcleri iinde en esnek ve yaygn olan utf-8 adl kod zcdr. Pythonda kod
konumlarn bayta evirmek iin encode() adl bir metottan yararlanabiliriz:
>>> unidiz = u"
sk"
>>> unidiz.encode("utf-8")
'\xc4\xb1\xc5\x9f\xc4\xb1k'
Unicode kod konumlar bayta evrildikten sonra artk bir unicode dizisi degil, karakter dizisi
olur:
>>> type(unidiz.encode("utf-8"))
<type 'str'>
Eger bir karakter dizisini unicode kod konumlar ile temsil etmek isterseniz decode()
metodundan yararlanabilirsiniz:
>>> kardiz.decode("utf-8")
u'\u0131\u015f\u0131k'
Bylece Pythondaki unicode destegine iliskin en nemli metotlar grms olduk. Artk
Pythonda unicodeye iliskin baz nemli modlleri de incelemeye geebiliriz...
231
category() metodu ise bir unicode dizisinin unicode sistemindeki kategorisini gsteriyor.
Yukarda verdigimiz rnege gre g harfinin kategorisi L1 yani Latin-1.
import codecs
f = codecs.open("deneme.txt", "w", encoding="utf-8")
f.write(u"
sk")
f.close()
Elbette codecs modlnn open() metodunu sadece yeni dosya olusturmak iin degil, her trl
dosya isleminde kullanabilirsiniz. Bu metot, dosya islemleri konusunu islerken grdgmz
open() metoduyla birbirine ok benzer. Tpk o metotta oldugu gibi codecs.open() metodunda
da dosyalar w, r, a gibi kiplerde aabilirsiniz.
232
BLM 13
Biim Dzenleyiciler
Grdgnz gibi bu kodlar hata verdi. nk karakter dizisi iindeki iki adet %s ifadesine
karslk, karakter dizisinin dsnda tek bir deger var (istihza). Halbuki bizim syle bir kod
yazmamz gerekiyordu:
>>> isim = "istihza"
>>> print "%s adl ki
sinin mekan \
... www.%s.com adresidir." %(isim, isim)
Bu defa herhangi bir hata mesaj almadk. nk bu kodlarda, olmas gerektigi gibi, karakter
dizisi iindeki iki adet %s ifadesine karslk, dsarda iki adet deger var.
Bu arada, yukardaki rnek, biim dzenleyiciler hakknda bize nemli bir bilgi daha veriyor.
Dikkat ettiyseniz, karakter dizisi dsnda tek bir deger varsa bunu parantez iinde belirtmemize
233
gerek yok. Ama eger deger says birden fazlaysa bu degerleri bir demet (tuple) olarak
tanmlamamz gerekiyor. Yani bu degerleri parantez iinde gstermeliyiz. Aksi halde
yazdgmz kodlar hata verecektir.
Yukardaki rneklerde % adl biim dzenleyiciyi s karakteriyle birlikte kullandk.
Esasnda en yaygn ift de budur. Yani etraftaki Python programlarnda yaygn olarak %s
yapsn grrz. Ancak Pythonda % biim dzenleyicisiyle birlikte kullanlabilecek tek
karakter s degildir. Daha nce de dedigimiz gibi, s karakteri string, yani karakter
dizisi ifadesinin ksaltmasdr. Yani aslnda %s yaps Pythonda zel olarak karakter
dizilerini temsil eder. Peki, bu ne demek oluyor? Bir karakter dizisi iinde %s yapsn
kullandgmzda, dsarda buna karslk gelen degerin bir karakter dizisi veya karakter dizisine
evrilebilecek bir deger olmas gerek. Bunun tam olarak ne demek oldugunu biraz sonra daha
net bir sekilde anlayacagz. Biraz sabr, diyerek yolumuza devam edelim.
Grdgnz gibi, Pythonda biim dzenleyici olarak kullanlan simge ayn zamanda yzde
(%) anlamna da geliyor. O halde size syle bir soru soraym: Acaba 0dan 100e kadar olan
saylarn basna birer yzde isareti koyarak bu saylar nasl gsterirsiniz? %0, %1, %10, %15
gibi... nce syle bir sey deneyelim:
>>> for i in range(100):
...
print "%s" %i
...
Bu kodlar tabii ki sadece 0dan 100e kadar olan saylar ekrana dkmekle yetinecektir.
Saylarn basnda % isaretini gremeyecegiz...
Bir de syle bir sey deneyelim:
>>> for i in range(100):
...
print "%%s" %i
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
TypeError: not all arguments converted during string formatting
Burada % isaretini arka arkaya iki kez kullanarak bir adet % isareti elde ettik. Daha sonra
da normal bir sekilde %s biimini kullandk. Yani adet % isaretini yan yana getirmis
olduk.
234
13.1.1 d Harfi
Yukarda grdgmz s harfi nasl karakter dizilerini temsil ediyorsa, d harfi de saylar
temsil eder. Isterseniz kk bir rnekle aklamaya alsalm durumu:
>>> print "
Subat ay bu yl %d gn ekiyor" %28
Subat ay bu yl 28 gn ekiyor.
Grdgnz gibi, karakter dizisi iinde %s yerine bu defa %d gibi bir sey kullandk.
Buna uygun olarak da ds tarafta 28 saysn kullandk. Peki, yukardaki ifadeyi syle de
yazamaz myz?
>>> print "
Subat ay bu yl %s gn ekiyor" %28
Elbette yazabiliriz. Bu kod da bize dogru kt verecektir. nk daha nce de dedigimiz gibi,
s harfi karakter dizilerini ve karakter dizisine evrilebilen degerleri temsil eder. Pythonda
saylar karakter dizisine evrilebildigi iin %s gibi bir yapy hata almadan kullanabiliyoruz.
Ama mesela syle bir sey yapamayz:
>>> print "
Subat ay bu yl %d gn ekiyor" %"yirmi sekiz"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: %d format: a number is required, not str
Grdgnz gibi bu defa hata aldk. nk d harfi yalnzca say degerleri temsil edebilir.
Bu harfle birlikte karakter dizilerini kullanamayz.
Dogrusunu sylemek gerekirse, d harfi aslnda tamsay (integer) degerleri temsil eder. Eger
bu harfin kullanldg bir karakter dizisinde deger olarak bir kayan noktal say (float) verirsek,
bu deger tamsayya evrilecektir. Bunun ne demek oldugunu hemen bir rnekle grelim:
>>> print "%d" %13.5
13
13.1.2 i Harfi
Bu harf de integer, yani tamsay kelimesinin ksaltmasdr. Kullanm ve islev olarak, d
harfinden hi bir fark yoktur.
235
13.1.3 o Harfi
Bu harf octal (sekizlik) kelimesinin ksaltmasdr. Adndan da anlaslacag gibi, sekizlik
dzendeki saylar temsil eder. rnegin:
>>> print "%i saysnn sekizlik dzendeki kar
sl
g \
... %o saysdr." %(10, 10)
10 saysnn sekizlik dzendeki kar
sl
g 12 saysdr.
13.1.4 x Harfi
Bu harf hexadecimal, yani onaltlk dzendeki saylar temsil eder:
>>> print "%i saysnn onaltlk dzendeki kar
sl
g \
... %x saysdr." %(20, 20)
20 saysnn onaltlk dzendeki kar
sl
g 14 saysdr.
13.1.5 X Harfi
Bu da tpk x harfinde oldugu gibi, onaltlk dzendeki saylar temsil eder. Ancak bunun
fark, harfle gsterilen onaltlk saylar byk harfle temsil etmesidir:
>>> print "%i saysnn onaltlk dzendeki kar
sl
g \
... %X saysdr." %(10, 10)
10 saysnn onaltlk dzendeki kar
sl
g A saysdr.
13.1.6 f Harfi
Pythonda karakter dizilerini biimlendirirken s harfinden sonra en ok kullanlan harf f
harfidir. Bu harf Ingilizcedeki float, yani kayan noktal say kelimesinin ksaltmasdr.
Adndan da anlaslacag gibi, karakter dizileri iindeki kayan noktal saylar temsil etmek iin
kullanlr:
>>> print "Dolar %f TL olmu
s..." %1.4710
Dolar 1.471000 TL olmu
s...
236
Eger yukardaki komutun kts sizi sasrttysa okumaya devam edin. Biraz sonra bu kty
istedigimiz kvama nasl getirebilecegimizi inceleyecegiz...
13.1.7 c Harfi
Bu harf de Pythondaki nemli karakter dizisi biimlendiricilerinden biridir. Bu harf tek bir
karakteri temsil eder:
>>> print "%c" %"a"
a
Ama:
>>> print "%c" %"istihza"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: %c requires int or char
Grdgnz gibi, c harfi sadece tek bir karakteri kabul ediyor. Karakter says birden fazla
oldugunda bu komut hata veriyor.
c harfinin bir baska zelligi de ASCII tablosunda saylara karslk gelen karakterleri de
gsterebilmesidir:
>>> print "%c" %65
A
ASCII tablosunda 65 says A harfine karslk geldigi iin yukardaki komutun kts A
harfini gsteriyor. Eger isterseniz c harfini kullanarak btn ASCII tablosunu ekrana
dkebilirsiniz:
>>> for i in range(128):
...
"%s ==> %c" %(i, i)
Eger bu ASCII tablosuna tam anlamyla tablovari bir grnm vermek isterseniz syle bir
sey yazabilirsiniz:
a = ["%s = %c" %(i, i) for i in range(32, 128)]
for i in range(0, 120, 7):
a.insert(i, "\n")
for v in a:
print v.rjust(8),
237
Ayrca 120 yerine farkl saylar koyarak hangi saynn yetersiz kaldgn, hangi saynn fazla
geldigini de inceleyebilirsiniz.
Son olarak da, karakter dizisi metotlarn islerken grdgmz rjust() adl metot yardmyla,
tabloya girecek karakterleri 8 karakterlik bir alan iinde saga yaslayarak ekrana dktk.
Stokta ka kilo elma kaldgn grenmek isteyen kullancya bu bilgiyi su sekilde verebiliriz:
>>> mal = "elma"
>>> print stok[mal]
10
Ancak bundan daha iyisi, kty biraz biimlendirerek kullancya daha temiz bir bilgi
sunmaktr:
>>> mal = "elma"
>>> print "Stokta %d KG %s kald!" %(stok["elma"], mal)
Stokta 10 KG elma kald!
Ya da mevcut stoklarn genel durumu hakknda bilgi vermek iin syle bir yol tercih
edebilirsiniz:
238
Burada ncelikle stok szlgmz tanmladk. Daha sonra for k, v in stok.items() satr ile,
stok szlgnn btn gelerini teker teker k ve v adl iki degiskene atadk. Bylece
szlk iindeki anahtarlar k degiskenine; degerler ise v degiskenine atanms oldu. Son
olarak da print %s\t=\t%s KG%(k, v) satryla bu k ve v degiskenlerini rnegin elma =
10 KG ktsn verecek sekilde biimlendirip ekrana yazdrdk. Burada meyve adlaryla
meyve miktarlar arasndaki mesafeyi biraz amak iin \t adl kas dizisinden
yararlandgmza dikkat edin.
Yukardaki rnekler, karakter dizisi biimlendirme kavramnn en temel kullanmn
gstermektedir. Ancak isterseniz Pythondaki karakter dizisi biimlendiricilerini kullanarak
daha karmask islemler de yapabilirsiniz.
Buradaki yap ilk anda gznze karmask gelmis olabilir. Ancak aslnda olduka basittir.
stelik bu yap epey kullansldr ve baz durumlarda islerinizi bir hayli kolaylastrabilir.
Burada yaptgmz sey, %s adl karakter dizisi biimlendiricisindeki % ve %s
karakterleri arasna degisken adlar yerlestirmekten ibarettir. Burada belirttigimiz degisken
adlarn daha sonra karakter dizisi dsnda bir szlk olarak tanmlyoruz.
Bir de su rnege bakalm:
# -*- coding: utf-8 -*randevu = {"gun_sayi": 13,
"ay": "Ocak",
"gun": u"ar
s.",
"saat": "17:00"}
print u"%(gun_sayi)s %(ay)s %(gun)s \
%(saat)s'da bulu
salm!" %randevu
239
%{"gun_sayi": 13,
"ay": "Ocak",
"gun": u"ar
s.",
"saat": "17:00"}
Kodlar bu sekilde yazdgmzda karakter dizisi dsnda % isaretinden sonra demet yerine
szlk kullandgmza dikkat edin.
Pythonun bize sundugu bu yap karakter dizisi iindeki degiskenlerin neler oldugunu takip
edebilmek asndan epey kullansl bir aratr.
Burada karakter dizisinin dsnda belirttigimiz say 1.4710 oldugu halde ktda elde ettigimiz
say 1.471000... Grdgnz gibi, elde ettigimiz say tam istedigimiz gibi degil. Ama eger
arzu edersek bu kty ihtiyalarmza gre biimlendirme imknna sahibiz. Bu blmde,
Pythondaki saylar nasl hassas biimlendirecegimizi inceleyecegiz. Kk bir rnekle
baslayalm:
>>> "%f" %1.4
'1.400000'
Grdgnz gibi, noktadan sonra istedigimizden daha fazla sayda basamak var. Diyelim ki
biz noktadan sonra sadece 2 basamak olsun istiyoruz:
>>> "%.2f" %1.4
'1.40'
Burada yaptgmz sey, % isareti ile f karakteri arasna bir adet nokta (.) ve istedigimiz
basamak saysn yerlestirmekten ibaret... Bir de su rnege bakalm:
>>> "%.2f" %5
'5.00'
240
Grdgnz gibi, f yerine d karakterini kullandgmzda .3 gibi bir ifade, saylarn sol
tarafn sfrlarla dolduruyor. Burada dikkat ederseniz, ktda adet 0 yok. .3 ifadesinin
yaptg sey, toplam basamakl bir tamsay olusturmaktr. Eger tamsay normalde tek
basamakl ise, bu ifade o tek basamakl saynn soluna iki sfr koyarak basamak saysn 3e
tamamlar. Eger say 3 veya daha fazla sayda basamaktan olusuyorsa, .3 ifadesinin herhangi
bir etkisi olmaz... Bu yapnn tam olarak ne ise yaradgn anlamak iin farkl saylarla
denemeler yapmanz tavsiye ederim.
Bu zelligi syle bir is iin kullanabilirsiniz:
>>> for i in range(11):
...
print "%.3d" %i
...
000
001
002
003
004
005
006
007
008
009
010
Yukardaki zelligin, daha nce karakter dizisi metotlarn islerken grendigimiz zfill()
metoduna benzedigini farketmissinizdir. Ayn seyi zfill() metodunu kullanarak syle
yapyorduk:
>>> for i in range(11):
...
print str(i).zfill(3)
...
000
001
241
002
003
004
005
006
007
008
009
010
Isterseniz konuyu daha iyi anlayabilmek iin daha basit bir rnek verelim:
>>> for i in range(20):
...
print "%2d" %i
...
0
1
2
3
4
5
6
7
8
9
10
11
12
242
13
14
15
16
17
18
19
Dikkat ederseniz burada 10dan nceki saylar saga yaslanms durumda. Yukardaki kodlar
herhangi bir biimlendirici iermeyecek sekilde yazarsanz fark daha net grebilirsiniz:
>>> for i in range(11):
...
print i
...
0
1
2
3
4
5
6
7
8
9
10
Fark gryorsunuz.. Bu defa saylar normal bir sekilde sola yaslanms durumda.
Yine bu biimlendiricileri kullanarak karakter dizileri arasnda belli sayda bosluklar da
brakabilirsiniz. Mesela:
>>> print "merhaba %10s dnya" %""
merhaba dnya
Buna benzer bir seyi kas dizilerinden biri olan \t ile de yapabiliyoruz. Ancak \tyi
kullandgmzda bosluk miktarnn tam olarak ne kadar olacagn kestiremeyiz. Karakter dizisi
biimlendiricileri ise bize bu konuda ok daha fazla kontrol imkn verir.
243
Karakter dizilerini hem hizalamak hem de sol taraflarna sfr eklemek iin de syle bir sey
yapyoruz:
>>> for i in range(11):
...
print "%3.2d"%i
Grdgnz gibi nokta isaretinden nce getirdigimiz say karakter dizisinin hizalanma
miktarn gsterirken, noktadan sonra getirdigimiz say karakter dizisinin sol tarafna
eklenecek sfrlarn saysn gsteriyor.
Eger yukardaki rneklerde f adl biimlendirme karakterini kullanrsanz, sonu biraz farkl
olacaktr:
>>> print "kur: %8.3f" %1.2
kur: 1.200
Bu isaret ve karakterlerin tam olarak nasl bir etki olusturdugunu daha iyi anlayabilmek iin
kendi kendinize rnekler yapmanz tavsiye ederim...
244
Burada karakter dizisini nce bir degiskene atadk, daha sonra bu degiskene format()
metodunu uyguladk.
Grdgnz gibi, bu metodun gerekten de teki karakter dizisi metotlarndan hibir fark
yok. Bu metot da digerleriyle tamamen ayn sekilde kullanlyor. Yap olarak ise, eski
yntemdeki % isaretinin yerini {} isaretleri alyor.
format() metodunun baz ilgin zellikleri bulunur. Mesela {} isaretleri iinde bir sra
numaras vererek, format() metoduna verdigimiz parametrelerin srasn istedigimiz sekilde
dzenleyebiliriz:
>>> print '{1} ve {0} iyi bir ikilidir!'.format('Python', 'Django')
Django ve Python iyi bir ikilidir!
Normal sartlar altnda, {} isaretleri arasnda herhangi bir say belirtmedigimizde Python
format() metodunun parantezleri arasndaki degerleri, karakter dizisinin iine, parantez iinde
bulunduklar sra ile yerlestirecektir. Yukardaki rnekten de grdgnz gibi, biz bu
sralamay degistirme imkanna sahibiz. Yukarda yazdgmz kod sayesinde Django
degerini, karakter dizisi iine Python degerinden nce yerlestirebildik.
% isareti ile biimlendirme konusunu anlatrken bahsettigimiz biimlendirme
karakterlerinden elbette format() metodunda da yararlanabiliriz. Su
rneklere dikkatlice bakn:
>>> print '{:c}'.format(100) #saynn karakter kar
sl
g
d
>>> print '{:x}'.format(100) #saynn onaltlk kar
sl
g
64
>>> print '{:o}'.format(100) #saynn sekizlik kar
sl
g
144
>>> print '{:f}'.format(100) #saynn kayan noktal kar
sl
g
100.000000
>>> print '{:.2f}'.format(100) #noktadan sonraki hane says
100.00
245
Bylece Pythondaki nemli bir konuyu daha geride brakms olduk. Aslnda burada
sylenecek birka sey daha olsa da yukardakilerin Python programlar yazarken en ok
ihtiyacnz olacak bilgiler oldugunu gnl rahatlgyla syleyebiliriz.
246
BLM 14
math Modl
Pythondaki ileri dzey modllerden biri olan math modl matematikle ugrasanlarn
islerini bir hayli kolaylastracak metotlar ve fonksiyonlar barndrr.
Pythonda matematiksel fonksiyonlar math modl ile kullanmaktayz. Simdi
math
modlmzn ierigini grelim. Unutmadan modlmz alsmamza agralm:
>>> import math
ierdigi fonksiyonlar
asagdaki komutu vererek grelim:
>>> dir(math)
['__doc__', '__file__', '__name__', 'acos', 'asin', 'atan',
'atan2', 'ceil', 'cos', 'cosh', 'degrees', 'e', 'exp',
'fabs', 'floor', 'fmod', 'frexp', 'hypot', 'ldexp', 'log',
'log10', 'modf', 'pi', 'pow', 'radians', 'sin', 'sinh',
'sqrt', 'tan', 'tanh']
Modlmzn ierigini de grdgmze gre simdi kosins, sins, tanjant, pi, karekk, sl
ifadeler gibi fonksiyonlarla ilgili rneklerle kullanmn anlamaya alsalm.
seklindedir. Yukardaki kodu yazdgmzda Python bize cevap olarak sunu gsterir:
8.0
pow() fonksiyonunun kullanmnda parantez ierisindeki ilk say taban, ikinci say ise ss
gstermektedir.
247
Bu kod ile sunu demis olduk: 4 ile 3 bl, pi says ile arp, sonra da sonucu 2nin 3nc
kuvveti ile arp.
Python bize cevap olarak sunu gsterdi:
33.510321638291124
Tabii ki bu islemleri Kwrite programnda bir dosya aarak asagdaki gibi de yazabiliriz:
#/usr/bin/env python
# -*- coding: utf-8 -*from __future__ import division
import math
r = input("Krenin yarapn giriniz:")
hacim = 4 / 3 * math.pi * math.pow(r, 3)
kodunu yazp ENTER tusuna bastgmzda Python bize asagdaki sonucu gsterir:
3.0
248
249
alnacak saydr:
>>> math.log10(10)
Dnen cevap:
1.0
x burada radyana evrilecek amzdr. rnek olarak 45 derecelik bir a verelim ve radyan
karslgn bulalm:
>>> math.degrees(45)
2578.3100780887044
x burada dereceye evrilecek radyandr. rnek olarak 45 radyanlk bir a verelim ve derece
karslgn bulalm:
>>> math.radians(45)
0.78539816339744828
Kosins, Sins ve Tanjant ile ilgili fonksiyonlara girmeden nce belirtmem gereken nemli bir
nokta bulunmaktadr. Bu fonksiyonlarda a olarak Python radyan kullanmaktadr. Bu yzden
aldgmz sonular okulda grendigimiz degerlerden farkl olacaktr. Bunu da radians()
fonksiyonu ile dzeltecegiz.
250
1.0
cevabn verir.
>>> math.cos(45)
0.52532198881772973
Yukarda grdgmz zere bizim bekledigimiz cevap bu degil. Biz 0.7071 gibi bir deger
bekliyorduk. Bunu asagdaki sekilde dzeltebiliriz:
>>> math.cos(math.radians(45))
0.70710678118654757
Simdi
cevabn verir.
>>> math.sin(45)
0.85090352453411844
Evet yukarda grdgmz zere bizim bekledigimiz cevap bu degil. Biz 0.7071 gibi bir
deger bekliyorduk. Bunu asagdaki sekilde dzeltebiliriz:
>>> math.sin(math.radians(45))
0.70710678118654746
Simdi
251
0.0
cevabn verir.
>>> math.tan(45)
1.6197751905438615
Yukarda grdgmz zere bizim bekledigimiz cevap bu degil. Biz ~1.000 (yaklask) gibi bir
deger bekliyorduk. Bunu asagdaki sekilde dzeltebiliriz:
>>> math.tan(math.radians(45))
0.99999999999999989
BLM 15
ve nbellekleme
Mekanizmas
Pythonda her nesnenin bir kimligi (identity) vardr. Kabaca sylemek gerekirse, kimlik denen
sey esasnda o nesnenin bellekteki adresini temsil eder. Pythondaki her nesnenin kimligi
essiz, tek ve benzersizdir. Peki, bir nesnenin kimligine nasl ulasrz? Pythonda bu isi
yapmamz saglayacak basit bir fonksiyon bulunur. Bu fonksiyonun ad id(). Yani
Ingilizcedeki identity (kimlik) kelimesinin ksaltmas. Simdi
Grdgnz gibi, Python a degiskenini ve 100 saysn ayr ayr sorgulamamza ragmen
ayn kimlik numaralarn gsterdi. Bu demek oluyor ki, Python iki adet 100 says iin
bellekte iki farkl nesne yaratmyor. Ilk kullanmda nbellegine aldg sayy, ikinci kez
ihtiya oldugunda bellekten alp kullanyor. Ama bir de su rneklere bakalm:
>>> a = 1000
>>> id(a)
138406552
>>> id(1000)
137992088
253
Bu defa Python a degiskeninin tuttugu 1000 says ile teki 1000 says iin farkl kimlik
numaralar gsterdi. Bu demek oluyor ki, Python a degiskeninin tuttugu 1000 says iin ve
dogrudan girdigimiz 1000 says iin bellekte iki farkl nesne olusturuyor. Yani bu iki 1000
says Python asndan birbirinden farkl. Bu durumu grebilecegimiz baska bir yntem de
Pythondaki is islecini kullanmaktr. Deneyelim:
>>> a is 1000
False
Grdgnz gibi, Python False (Yanls) ktsn suratmza bir tokat gibi arpt... Peki, bu
ne anlama geliyor? Syle
Ama...
>>> a == 1000
True
Burada is isleci a degiskeninin tuttugu veri ile 1000 saysnn ayn kimlik numarasna sahip
olup olmadgn sorgularken, == isleci a degiskeninin tuttugu verinin 1000 olup
olmadgn denetliyor. Yani is islecinin yaptg sey kabaca su oluyor:
>>> id(a) == id(1000)
False
Simdiye
Burada True ktsn aldk. Bir de == isleci ile bir karslastrma yapalm:
>>> a == "python"
True
254
Blm 15. Pythonda id() Fonksiyonu, is Isleci
ve nbellekleme Mekanizmas
False
Ama...
>>> a == "python gl ve kolay bir programlama dilidir"
True
Bu kod 1000 aralgndaki iki say grubunu karslastrp, kimlikleri ayn olan saylar ekrana
dkyor... Yani bir bakma Pythonun hangi sayya kadar nbellekleme yaptgn gsteriyor.
Burada aldgmz sonuca gre syle bir denetleme islemi yapalm:
>>> a = 256
>>> a is 256
True
>>> a = 257
>>> a is 257
False
255
Grdgnz gibi, ierik ayn oldugu halde iki listenin kimligi birbirinden farkl... Python bu
iki listeyi bellekte iki farkl adreste depoluyor. Ama bu listelerin ait oldugu veri tipi (yani
list), bellekte tek bir adreste depolanacaktr. nk bir nesnenin veri tipinin kendisi de
baslbasna bir nesnedir. Nasl liste2 nesnesinin kimlik numaras bu nesne ortalkta oldugu
srece ayn kalacaksa, btn listelerin ait oldugu byk list veri tipi nesnesi de tek bir
kimlik numarasna sahip olacaktr.
>>> id(type(liste))
>>> 3085544992L
>>> id(type(liste2))
3085544992L
Bu iki kt ayndr, nk Python list veri tipi nesnesi iin bellekte tek bir adres kullanyor.
Ama ayr listeler iin ayr adres kullanyor. Ayn durum tabii ki teki veri tipleri iin de
geerlidir. Mesela dict veri tipi (szlk)
>>> sozluk1 = {}
>>> id(sozluk1)
3082285236L
>>> sozluk2 = {}
>>> id(sozluk2)
3082285916L
Ama tpk list veri tipinde oldugu gibi, dict veri tipinin nesne kimligi de hep ayn
olacaktr:
>>> id(type(sozluk1)
3085549888L
>>> id(type(sozluk2)
3085549888L
256
Blm 15. Pythonda id() Fonksiyonu, is Isleci
ve nbellekleme Mekanizmas
print
else:
print
print
print
is islecini ayn zamanda bir nesnenin None degerine es olup olmadgn kontrol etmek iin
de kullanabilirsiniz. nk None degeri bellekte her zaman tek bir adreste depolanacak,
dolaysyla bu degere gnderme yapan btn nesneler iin ayn bellek adresi kullanlacaktr:
>>> if b is None:
... .......
gibi...
Szn z, is isleci iki nesne arasnda ierik karslastrmas yapmak iin gvenli degildir.
nk Python baz nesneleri (zellikle ufak boyutlu nesneleri) nbellegine alrken, baz
nesneler iin her defasnda farkl bir depolama islemi yapmaktadr. Ierik karslastrmas iin
== veya != islelerini kullanmak daha dogru bir yaklasm olacaktr.
257
BLM 16
GNU/Linux kullananlarn Pythonun etkilesimli kabuguna ulasmak iin yapmalar gereken tek
sey komut satrnda python yazp ENTER tusuna basmaktr. nk GNU/Linux dagtmlar
Python paketini sisteme eklerken, alstrlabilir Python dosyasn da /usr/bin klasr iine
atar. Bu sayede GNU/Linux kullananlar zahmetsiz bir sekilde Pythonu kurcalamaya
baslayabilirler... Ama Windows kullananlar iin ayn seyi syleyemiyoruz. nk Windows
kullananlar http://www.python.org adresinden Python programn indirip bilgisayarlarna
kurduklarnda Python otomatik olarak YOLa (PATH) eklenmiyor. Bu durumda Pythonun
etkilesimli kabuguna ulasmak iin Baslat/Programlar/Python 2.x/Python (Command Line)
yolunu takip etmek gerekiyor. Ancak etkilesimli kabuga bu sekilde ulasmann baz
dezavantajlar var. rnegin bu sekilde kabuga ulastgnzda Pythonu istediginiz dizin iinde
baslatamams oluyorsunuz. Bu sekilde Pythonun etkilesimli kabugu, Pythonun kurulu
oldugu C:/Python2x dizini iinde alacaktr. Etkilesimli kabuk akken hangi dizinde
oldugunuzu srasyla su komutlar vererek grenebilirsiniz:
>>> import os
>>> os.getcwd()
258
Bilgisayarm simgesine sag tkladktan sonra alan mennn en altnda yer alan zelliklere
(Properties) giriyoruz.
Bu girdigimiz yerde Gelismis (Advanced) adl bir sekme grecegiz. Bu sekmeyi ayoruz.
Bu ekranda Sistem Degiskenleri (System Variables) blmnde yer alan liste iinde Path
gesini buluyoruz. Listedeki geler alfabe srasna gre dizildigi iin Pathi bulmanz zor
olmayacaktr.
Path gesi seili iken, Sistem degiskenleri blmndeki Dzenle (Edit) dgmesine
tklyoruz. Karsmza syle bir sey geliyor: (Asagdaki ekran grntsnde Sistem
Degiskenleri blmndeki Path gesini de listede grebilirsiniz.)
Bu ekrandaki listenin en sonunda grnen ;C:\Python26 gesine dikkat edin. Siz de listenin
sonuna, sisteminizde kurulu olan Python srmne uygun ifadeyi ekleyeceksiniz. Yukardaki
ekran grnts Pythonun 2.6 srmne gre. Eger sizde mesela Python 2.7 kuruluysa oraya
;C:\Python27 yazacaksnz.
Sizdeki srmn tam adn grenmek iin C:/ dizinini kontrol edebilirsiniz. Bu klasrn ad
sizdeki srme gre farkllk gsterebilir. Dogru srm numarasn gerekli yere yazdktan
sonra Tamam dgmelerine basarak tekrar masastne dnyoruz.
Simdi
259
260
261
262
263
Etkilesimli kabuktan kmak iin nce CTRL+Z tuslarna, ardndan da ENTER tusuna
basyoruz. Artk, cmd ile ulastgmz bu komut satrnda su komutu vererek Python
programlarn alstrabiliriz:
python program_ad
Windows komut satr Pythonun Windowsta sundugu komut satrndan biraz daha
yeteneklidir. cmd komutu ile ulastgnz ekranda kopyalama/yapstrma islemleri de
yapabilirsiniz.
Not: Bu konuyla ilgili herhangi bir sorunuz olmas halinde kistihza@yahoo.com adresine
yazabilirsiniz.
264
BLM 17
Python programlama dilini yakndan takip ediyorsanz, su anda piyasada iki farkl Python
srmnn oldugu dikkatinizi ekmis olmal. Nisan 2013 tarihi itibariyle resmi Python
sitesinden [http://www.python.org/download] indirebilecegimiz en yeni Python srmleri
Python 2.7.4 ve Python 3.3.1dir.
Eger bir Python srm 2 says ile baslyorsa (mesela 2.7.4), o srm Python 2.x serisine
aittir. Yok eger bir Python srm 3 ile baslyorsa (mesela 3.3.1), o srm Python 3.x
serisine aittir.
Peki neden piyasada iki farkl Python serisi var ve bu bizim iin ne anlama geliyor?
Python programlama dili 1990 ylndan bu yana gelistirilen bir dil. Bu sre iinde pek ok
Python program yazld ve insanlarn kullanmna sunuldu. Su
anda piyasadaki ogu Python
program 2.x serisinden bir srmle yazlms durumda. 3.x serisi ise yeni yeni yaygnlk
kazanyor.
Not: Biz bu makalede kolaylk asndan Pythonn 3.x serisini Python3, 2.x serisini ise
Python2 olarak adlandracagz.
Python3, Python2ye gre hem ok daha gldr, hem de Python2nin hatalarndan
arndrlmstr. Python3teki byk degisikliklerden tr, Python2 ile yazlms bir program
Python3 altnda alsmayacaktr. Ayn durum bunun tersi iin de geerlidir. Yani Python3
kullanarak yazdgnz bir program Python2 altnda alsmaz.
Dedigimiz gibi, piyasada Python2 ile yazlms ok sayda program var. Iste bu sebeple Python
gelistiricileri uzun bir sre daha Python2yi gelistirmeye devam edecek. Elbette gelistiriciler
bir yandan da Python3 zerinde alsmay ve bu yeni seriyi gelistirmeyi srdrecek.
Farkl Python serilerinin var olmasndan tr, Python ile program yazarken hangi seriye ait
bir srm kullandgnz bilmeniz, yazacagnz programn kaderi asndan byk nem tasr.
Python 3.x serisinin ilk kararl srm 3 Aralk 2008 tarihinde yaymland. Ancak Python3
eski srmlerle uyumlu olmadg iin insanlar hala Python3e gemekte tereddt ediyor.
nk hem etraftaki Python programlar, hem Pythonla ilgili kaynaklar hem de nemli
nc sahs modlleri henz Python3e tasnmad. Dolaysyla, henz Python3e tasnmams
modllere bagmllk duyan Python programlarnn yazarlar Python3e geis konusunda ayak
diretiyor.
265
Python gelistiricileri, bir yandan Python3 gelistirmekle ugrasrken, bir yandan da insanlarn
Python3e geisini hzlandrmak ve korkular gidermek iin bilgilendirici ve yreklendirici
makaleler yaymlyor. Bu yreklendirici makalelerden biri de
http://wiki.python.org/moin/Python2orPython3 adresinde bulunuyor. Bu makalede, Python
kullanclarnn sklkla sordugu Python3 m yoksa Python2yi mi kullanmalym?
sorusuna bir cevap vermeye alsyor Python gelistiricileri. . . Yukardaki makalenin Trke
evirisine http://www.istihza.com/blog/python-3-ve-python-2.html/ adresinden ulasabilirsiniz.
Peki Python3 bize ne tr yenilikler getiriyor? Bu sorunun cevabn asagda madde madde
vermeye alsacagz.
Python3te print deyim degil, fonksiyondur
Bildiginiz gibi, Python2de herhangi bir seyi ekrana kt olarak vermek istedigimizde syle
bir kod yazyorduk:
>>> print "Merhaba Zalim Dnya!"
Burada print bir deyimdir, ama artk bu kod geerli degil. Python3te ayn kodu syle
yazmamz gerekiyor:
>>> print("Merhaba Zalim Dnya!")
Grdgnz gibi, Python2de print olarak yazdgmz kod Python3te print() biimini alyor.
Yani Python3te print bir fonksiyon olarak karsmza kyor.
Python3te range() fonksiyonu liste kts vermez
Python2de range() fonksiyonunu syle kullanyorduk:
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Grdgnz gibi, bu fonksiyon bize kt olarak bir liste veriyor. Gelelim Python3teki
duruma:
>>> range(10)
range(0, 10)
Bu komut, programn alstg sistemdeki mevcut alsma dizininin ierigini gsterir. Elbette
kt niyetli bir kullanc, rnegin sunucu zerinde alsan bir uygulamann ok daha ykc
komutlar alstrmasna yol aabilir.
Eger Python2deki input() fonksiyonunun bu islevini Python3te de elde etmek istersek su
komutu kullanacagz:
>>> eval(input())
Python3le birlikte bu ayrm ortadan kalkt. Artk btn karakter dizileri unicode olarak temsil
ediliyor. Bu ayrm ortadan kalktg iin, Python3te uelma tarz bir kod yazm herhangi bir
etkiye sahip olmayacaktr.
Python3te ntanml kodlama biimi utf-8dir
Bildiginiz gibi, iinde Trke karakterler barndran bir Python kodu yazdgmzda, eger
programn ilk satrna # -- coding: utf-8 -- veya # -- coding: cp1254 -- gibi bir satr
eklemezsek syle bir hata alyorduk:
267
Bunun sebebi Pythonun ntanml kod zcsnn ASCII olmas idi. Ama Python3le
birlikte ntanml kod zcs utf-8 oldugu iin artk # -- coding: utf-8 -- satrn yazmamza
gerek yok. Ancak eger dosyalarnz iin utf-8 dsnda farkl bir kodlama biimi
kullanacaksanz elbette uygun satr eklemeniz gerekiyor.
Pythonun ntanml kod zcsnn utf-8 olarak degistirilmesi Python2de yasadgmz pek
ok Trke probleminin de artk yasanmamasn saglayacaktr.
Python3te degisken adlarnda Trke karakterler kullanlabilir
Python2de degisken adlarnda Trke karakter kullanamyorduk. Ama Python3le birlikte bu
snrlama ortadan kaldrld. Dolaysyla artk syle degiskenler tanmlayabiliyoruz:
>>>
sekil = "dikdrtgen"
>>> say = 23
Bu sayede cik gibi tuhaf degisken adlar yerine k gibi daha anlaml degisken adlar
tanmlayabilecegiz...
Python3te blme islemleri tam sonu verir
Bildiginiz gibi, Python2de syle bir durum sz konusu idi:
>>> 5 / 2
2
Buradan 2.5 kts alabilmek iin yukardaki kodu syle yazmamz gerekiyordu:
>>> 5.0 / 2
2.5
Eger Python2deki kty Python3te de almak isterseniz yukardaki aritmetik islemi syle
yapmanz gerekiyor:
>>> 5 // 2
2
268
269
Bylece Python3le birlikte gelen temel yenilikleri bir rpda sralams olduk. Elbette
Python3le gelen baska yenilikler de var. Ancak yukarda sraladgmz zellikleri grenmeniz
Python2den Python3e geisinizin olabildigince sancsz olmasn saglamaya yetecektir.
En basta da syledigimiz gibi, Pythonun 3.x srmleri 2.x srmlerine kyasla byk
farkllklar ieriyor. Bu sebepten, Python2 ile yazlan programlar Python3 altnda
alsmayacak. Ancak srmler arasnda byk farklar olsa da nihayetinde dil yine ayn dil ve
Python3le gelen farkllklar programclara byk zorluklar getirecek cinsten degil.
Su
anda Python3n en byk sorunu, nc sahs modlleri asndan yetersiz olmas.
Pythonla ise yarar programlar yazmamz saglayan pek ok nc sahs modl henz
Python3e uyumlu degil. stelik GNU/Linux dagtmlarnn ezici ogunlugu da henz
ntanml olarak Pythonun 2.x srmlerini kullanyor. Bu ve buna benzer sebeplerden tr,
su an iin mantkl olan Python 2.x ile devam edip, bir yandan da Python 3.x ile ilgili
gelismeleri takip etmektir.
270
BLM 18
Bir programlama dilini ne kadar iyi bilirseniz bilin, bu programlama diliyle ne kadar gl
programlar yazarsanz yazn, eger programnz kullansl bir arayze sahip degilse
programnzn kullanc dzeyinde pek ilgi ekmeyecegi kesin...
Belki bilgisayar kurtlar komut satrndan alsan programlar kullanmaktan rahatsz
olmayacaktr, hatta sizi takdir de edecektir, ama son kullanc denen kesime hitap
etmediginiz srece dikkati ekmeniz g. Bu dikkati ekme meselesi de ogunlukla
kullancya prltl arayzler sunularak aslabiliyor. Diyelim ki komut satr zerinden harika
isler yapan muhtemesem bir program yazdnz ve programnz kullanma sundunuz. Son
kullanc, programnz kurup alstrmay denediginde verecegi ilk tepki: Ama bu program
alsmyor! olacaktr. Kzsak da kzmasak da durum bundan ibarettir.
Madem arayz denen sey bu kadar nemli su halde biz de bu blmde Pythonda nasl grafik
arayzler tasarlayabilecegimizi inceleyelim.
Pythonda arayz tasarm iin birden fazla seenegimiz var. Bunlar bir rpda sralayacak
olursak, seeneklerimizin sunlar oldugunu grrz:
PyGTK [http://www.pygtk.org/]
PyQt [http://www.riverbankcomputing.co.uk/news]
wxPython [http://www.wxpython.org/]
Tkinter [http://wiki.python.org/moin/TkInter]
Arayz tasarlamak zere gelistirilmis yukardaki alternatifler iinde biz Python tarafndan
resmi olarak desteklenen Tkinteri kullanacagz. Peki, neden tekiler degil de Tkinter?
ncelikle Tkinterin teki seeneklere kars en byk stnlg Python dagtm ile birlikte
gelmesidir. Dolaysyla Tkinter Python tarafndan resmi olarak desteklenen bir arayz tasarm
takmdr. Tkinter hem Windowsta hem de GNU/Linux zerinde rahatlkla alsabilir.
Aslnda artk gnmzde teki arayz takmlar da birden fazla platform zerinde
alsabilmektedir. Ama dagtmla birlikte geldigi iin Tkinter tekilere gre ok daha kolay ve
rahat bir sekilde kurulup kullanma hazr hale getirilebilir. Eger Windows kullanyorsanz,
Tkinter sizde zaten Pythonla beraber sisteminize kurulmustur. Eger GNU/Linux
kullanyorsanz, kullandgnz dagtmn paket yneticisini kullanarak tkinter paketini
sisteminize kurabilirsiniz. Farkl GNU/Linux dagtmlarnda bu paketin ad farkl olabilir.
271
Arayz denilen sey tabii ki penceresiz olmaz. Dolaysyla arayz programlamann ilk adm
alsan bir pencere yaratmak olacaktr.
Basta syledigimiz gibi, arayz tasarlarken Tkinter modlnden faydalanacagz. Daha nceki
yazlardan, Pythonda nasl modl import edildigini hatrlyorsunuz. Simdi
hemen
Pythonun etkilesimli kabugunda su komutu veriyoruz:
from Tkinter import *
Eger hibir sey olmadan alt satra geildiyse sorun yok. Demek ki sizde Tkinter modl ykl.
Ama eger bu komutu verdiginizde alt satra dsmek yerine bir hata mesaj alyorsanz, sebebi
gerekli modln, yani Tkinterin sizde ykl olmamasdr. Eger hal byleyse yapacagmz
islem ok basit: Kullandgmz GNU/Linux dagtmnn paket yneticisinden Tkinter
modln ieren paketi gidip kuracagz. Benim su anda kullandgm dagtm olan Ubuntuda
bu paketin ad python2.7-tk. Sizde de paketin ad buna benzer bir sey olmal. Mesela
Pardusta Tkinter modln kullanmak iin kurmanz gereken paketin ad python-tk.
Dedigim gibi, eger Windows kullanyorsanz, sizde Tkinter modl zaten ykldr. Windows
kullanclarnn Tkinter modln kullanabilmesi iin ayr bir sey yklemesine gerek yok.
Modlle ilgili ksm sag salim atlattysanz, artk su komutu verebilirsiniz:
Tk()
Eger buraya kadar herhangi bir hata yapmadysak, ekrana prl prl bir arayz penceresi
zpladgn grmemiz gerekiyor. ok gzel, degil mi? Burada komutumuzu sadece Tk()
seklinde kullanabilmemiz, yukarda Tkinter modln ie aktarma seklimizden
kaynaklanyor. Yani Tkinter modln from Tkinter import * seklinde ie aktardgmz iin
komutu Tk() seklinde yazmamz yeterli oluyor. Eger Tkinter modln import Tkinter
seklinde ie aktarsaydk, sadece Tk() dememiz yeterli olmayacakt. O zaman Tk() yerine
Tkinter.Tk() dememiz gerekirdi. Isterseniz modl import Tkinter seklinde ie aktarp, sadece
Tk() yazdgnzda ne tr bir hata aldgnz kontrol edebilirsiniz. Neyse, konuyu daha fazla
dagtmadan yolumuza devam edelim:
Grdgnz gibi Tk() komutuyla ortaya kan pencere, bir pencerenin sahip olmas gereken
btn temel zelliklere sahip. Yani pencerenin sag st ksesinde pencereyi kapatmaya
272
yarayan bir arp isareti, onun solunda pencereyi bytp kltmemizi saglayan karecik ve
en solda da pencereyi grev ubuguna indirmemizi saglayan isaret btn islevselligiyle
karsmzda duruyor. Ayrca farkedeceginiz gibi bu pencereyi istedigimiz gibi
boyutlandrmamz da mmkn.
Bu komutlar hangi platformda verdiginize bagl olarak, pencerenin grns farkl olacaktr.
Yani mesela bu komutlar Windowsta verdiyseniz, Windowsun renk ve sekil semasna uygun
bir pencere olusacaktr. Eger Gnome kullanyorsanz, pencerenin sekli semali, Gnomenin
renk ve sekil semasna uygun olarak KDEdekinden farkl olacaktr...
Yukarda verdigimiz Tk() komutuyla aslnda Tkinter modl iindeki Tk adl snf agrms
olduk. Bu snfn neye benzedigini merak eden arkadaslar /usr/lib/python2.7/lib-tk/ klasr
iindeki Tkinter.py modl iinde class Tk satrn arayarak bunun nasl bir sey olduguna
bakabilir. Bu arada herhangi bir hayal krklg yasamak istemiyorsanz, yukardaki from
Tkinter import * ve Tk() komutlarn verirken byk-kk harfe dikkat etmenizi tavsiye
ederim. nk Tkinter ile tkinter ayn seyler degildir...
Eger bir arayz olusturacaksak srekli komut satrnda alsamayz: Mutlaka yukarda
verdigimiz komutlar bir yere kaydetmemiz gerekir. Bunun iin hemen bos bir belge ap iine
su satrlar ekleyelim:
from Tkinter import *
Tk()
Belgemizin iine yukardaki kodlar yazdktan sonra bunu .py uzantl bir dosya olarak
kaydediyoruz ve normal Python dosyalarn nasl alstryorsak yle alstryoruz.
Isterseniz yukardaki kodu biraz derleyip toparlayalm. nk bu sekilde kodlarmz ok
aresiz grnyor. Yukardaki kodlar aslnda bir program iinde su sekilde grnecektir:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
mainloop()
Bu kodlar iinde grdgmz tek yenilik en sondaki mainloop() satr. Bu satr program iinde
bir dng olusturarak, kendisinden nce gelen kodlarla belirlenen zelliklere gre bir pencere
olusturulmasn saglyor. Bu satrla olusturulan dng sayesinde de olusturulan pencere (aksi
belirtilmedike veya kullanc pencereyi kapatmadka) ekranda hep ak kalabiliyor. Eger bu
son satr yazmazsak, penceremiz yine de olusur, ama biz pencereyi ekranda gremeyiz!.. Bu
arada buraya kk bir not dselim. Eger yazdgnz program Pythonla birlikte gelen bir
metin dzenleyici olan IDLE iinden alstryorsanz, yazdgnz programn son satrna
18.1. Pencere Olusturmak
273
mainloop() ifadesini yerlestirmeseniz bile programnz hatasz bir sekilde alsacaktr. Neden?
nk IDLE da Tkinter ile yazlms bir uygulamadr. Dolaysyla IDLEnin de kendisine ait
bir mainloop(), satr vardr. Yani siz kendi programnz iine mainloop()u koymasanz bile
IDLEnin kendi mainloop()u sizin programnzn da alsmasn saglayacaktr. Ancak
mainloop() satrn koymadgnz halde programnz IDLE iinden alssa da baska yerde
alsmayacaktr. O yzden bu mainloop() satrn mutlaka yerine koymalyz...
Dilerseniz kodlarmzn derli toplu hale getirilmis biimine syle bir bakalm:
Ilk satr anlatmaya gerek yok. Bunun ne oldugunu zaten biliyorsunuz. Ayrca zaten bildiginiz
gibi, bu satr sadece GNU/Linux kullanclarna yneliktir. Windows kullanclar bu satr
yazmasalar da olur.
Ikinci satrmz, yine bildiginiz gibi, programmz utf-8 ile kodlamamz saglyor. Windows
kullanclarnn utf-8 yerine cp1254 kullanmas gerekebilir...
nc satrda Tkinter modln programmzn iine aktaryoruz. Yani import ediyoruz.
Sonraki satrda, daha nce komut satrnda kullandgmz Tk() snfn bir degiskene atadk.
Nesne Tabanl Programlama konusundan hatrlayacagnz gibi, bir snf degiskene atama
islemine Pythonda instantiation, yani rnekleme ad veriliyordu. Iste biz de burada
aslnda Tkinter modl iindeki Tk() snfn rneklemis olduk...
Son satrdaki mainloop() ise yazdgmz pencerenin ekranda grnmesini saglyor.
Daha nceki derslerimizde Nesne Tabanl Programlama konusunu islerken, snfl yaplarn
genellikle arayz programlamada tercih edildigini sylemistik. Isterseniz yukarda yazdgmz
minik kodun snflar kullanlarak nasl yazlabilecegine bakalm:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
class Uygulama(object):
def __init__(self):
pass
pencere = Tk()
mainloop()
Tabii yukardaki snf rneginin pek bir anlam yok. Yaptg tek sey, ekrana bos bir pencere
getirmektir. stelik yukardaki rnek, kod yaps olarak mkemmel olmaktan uzak bir
iskeletten ibarettir. Btn eksikliklerine ragmen yukardaki rnek bize bir Tkinter programnn
snfl bir yap iinde temel olarak nasl grnecegini gsteriyor. Biz sayfalar ilerledike bu
snfmz daha iyi ve standart bir hale getirecegiz. Bu arada snfmz olustururken,
Pythonun yeni snf yapsna gre object adl snf miras aldgmza dikkat edin.
Simdiye
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
Ilk iki satrn ne oldugunu zaten biliyorsunuz, o yzden aklamaya gerek yok. Ondan sonra
gelen satrda da bildiginiz gibi Tkinter modln agrdk. Bir alt satrda ise yaptgmz sey
daha nce grdgmz Tk() komutuna bir ad vermekten, yani daha teknik bir dille ifade etmek
gerekirse Tk() snfn rneklemekten ibaret. Biz rnekleme (instantiation) islemi iin burada
pencere adn tercih ettik. Tabii ki siz isterseniz baska bir isim de kullanabilirsiniz. Hatta hi
isim vermeseniz de olur. Ama kullanm kolaylg ve performans asndan isimlendirmenin
zararn degil, yararn grrsnz. Simdi
Burada etiket adl yeni bir degisken olusturduk. Her zamanki gibi bu etiket ad zorunlu bir
isimlendirme degil. Istediginiz ismi kullanmakta serbestsiniz. Ancak degiskenin ismi nemli
olmasa da, ierigi nemlidir. pencere = Tk() komutu yardmyla en basta olusturdugumuz
pencereyi bir kutu olarak dsnrsek, etiket adyla tanmladgmz degisken de bu kutu
zerine yapstrlacak bir etiket olarak dsnlebilir. Bahsettigimiz bu kutunun zerine
etiketini yapstrmak iin Label adl zel bir islevden faydalanyoruz. (Bu arada label
kelimesi Ingilizcede etiket anlamna geliyor) Label ifadesini bu adla aklmza kazmamz
gerekiyor. Daha sonra bu Label ifadesine parametre olarak bir metin isliyoruz. Metnimiz
Elveda Zalim Dnya!. Metnimizin ad ise text. Label ifadesinde oldugu gibi, text
ifadesi de aklmza kazmamz gereken ifadelerden birisi. Bunu bu sekilde grenmemiz
gerekiyor. Kendi kendinize baz denemeler yaparak bu satrda neleri degistirip neleri
degistiremeyeceginizi incelemenizi tavsiye ederim...
Bir alt satrda etiket.pack() ifadesini gryoruz. Bu satr, yukardaki satrn islevli hale
gelmesini saglyor. Yani kutu zerine etiketi yapstrdktan sonra bunu alp kargoya
vermemize yaryor. Eger bu satr kullanmazsak bir gzel hazrlayp etiketledigimiz kutu
kargoya verilmemis olacag iin kullancya ulasmayacaktr.
En sondaki mainloop() ifadesini ise zaten tanyorsunuz: Yukarda yazdgmz btn kodlarn
dng halinde isletilerek bir pencere seklinde sunulmasn saglyor.
Kodlarmzn son hali syle olmal:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
etiket = Label(text="Elveda Dnya!")
etiket.pack()
275
mainloop()
Grdgnz gibi yine gayet sk, iinde Elveda Dnya! yazan bir pencere elde ettik.
Alstrma olsun diye, yukarda yazdgmz kodlara ok benzeyen baska bir rnek daha
yapalm:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
etiket = Label(text = "Resimler klasrn silmek \
istedi
ginizden emin misiniz?")
etiket.pack()
mainloop()
Simdi
Snfsz yapdaki kodlarn snfl yap iinde nasl degisikliklere ugradgna dikkat edin.
selfleri nasl kullandgmz inceleyin. Burada pencere = Tk() satryla Tk() snfn
rnekledikten sonra uyg = Uygulama() satryla da, yukardaki kodlarn iinde yazdgmz
Uygulama adl snfmz rnekliyoruz. En son satra da mainloop() ifadesini yerlestirmeyi
unutmuyoruz. Aksi halde olusturdugumuz pencere ekranda grnmeyecektir...
Yukardaki snfl kodu isterseniz su sekilde de yazabilirsiniz:
# -*- coding: utf-8 -*from Tkinter import *
class Uygulama(object):
def __init__(self):
self.araclar()
276
def araclar(self):
self.etiket = Label(text="Dosyay silmek \
istedi
ginize emin misiniz?")
self.etiket.pack()
pencere = Tk()
uyg = Uygulama()
mainloop()
Grdgnz gibi burada etiket gesini ayr bir fonksiyon olarak belirledik. Programnz
byyp birbirinden farkl geler iermeye basladg zaman bu geleri yukardaki sekilde
farkl blmlere ayrmak, kodlarnz daha dzenli bir hale getirecek, ileride kodlarnzn
bakmn yapmay kolaylastracaktr.
Eger bu snfl kodlar anlamakta zorluk ekiyorsanz, Nesne Tabanl Programlama konusunu
gzden geirebilirsiniz. Bu arada hatrlatalm, Tkinteri kullanmak iin snfl yaplar bilmek
zorunda degilsiniz. Ben de zaten bu sayfalarda snfl ve snfsz kullanmlar bir arada
verecegim. Eger snfl yapy anlamazsanz, sadece snfsz rneklerle de ilerleyebilirsiniz.
Ama yine de benim size tavsiyem, snflar grenmeniz ynnde olacaktr. nk internet
zerinde belli bir seviyeden sonra bu snfl yaplar hep karsnza kacaktr. Yani siz
kullanmasanz da, snflar kullanmay bilmeniz sizin iin faydal olacaktr. Bu arada dikkat
ederseniz, yukarda verdigimiz snfl son iki kod, daha nce verdigimiz snfl koddan daha
yetkin. Dedigimiz gibi, yeni zellikler grendike, kodlarmz adm adm standartlara daha
yakn hale getirecegiz.
Bu derste Tkinteri kullanarak basit bir pencereyi nasl olusturabilecegimizi grendik.
rneklerimizi hem snfl hem de snfsz kodlarla gsterdik. Tabii ki snfl kodlar bu tr
kk rneklerde ok lzumlu degildir. Ama byk bir projede alsrken snfl yap size
esneklik ve vakit kazandracak, kodlarnzn bakmn daha kolay yapmanz saglayacaktr.
Bu aklamalar da yaptgmza gre baska bir blme geebiliriz.
277
pencere = Tk()
baslik = pencere.title("Hi bir i
se yaramayan \
bir pencereyim ben...")
etiket= Label(text="...ama en azndan bir ba
sl
gm var.")
etiket.pack()
mainloop()
Grdgnz gibi pencereye baslk eklemek son derece kolay. Tek bir satrla isi
halledebiliyoruz. stelik herhangi bir paketleme islemi yapmamz da gerekmiyor.
Dilerseniz simdi yukardaki kodlar snfl yap iinde gsterelim:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
class Uygulama(object):
def __init__(self):
self.etiket = Label(text="Sabit diskiniz siliniyor...")
self.etiket.pack()
self.baslik = pencere.title("ok nemli Uyar!")
pencere = Tk()
uyg = Uygulama()
mainloop()
Bu kodlar iindeki tek yenilik, self.baslik = ... satrdr. Geri kalan ksmlar zaten nceki
rneklerden de biliyorsunuz.
Pencerelerle ilgili daha karmask zelliklere gemeden nce isterseniz burada bir durup
simdiye kadar grendiklerimizi ok ksa bir sekilde zetleyelim:
Tkinterle arayz tasarm yapabilmek iin ncelikle from Tkinter import * diyerek gerekli
modl ie aktarmamz gerekiyor.
Ardndan Tk() yardmyla bos bir pencere olusturuyoruz. Kullanm kolaylg ve performans
asndan Tk() ifadesini isimlendirerek bir degiskene atamay (yani Tk() snfn rneklemeyi)
tercih edebilirsiniz. rnegin; uygulama = Tk(). Performans asndan snflarmz rneklemek
gerekir, nk Nesne Tabanl Programlama adl dersten hatrlayacagnz gibi, rneklenmeyen
snflar p toplama (garbage collection) ad verilen bir srece tabi tutulacaktr.
Bundan sonra pencere iine yazmak istedigimiz ifadeyi ieren bir etiket hazrlamamz
gerekiyor. Bu etiketi alp Tk() isimli kutunun zerine yapstracagz. Bu is iin bize Label()
adl ara yardmc olacak. Bu fonksiyonun parametresi olarak yazacagmz text adl
degiskene istedigimiz metni girebiliriz. Mesela: oyun = Label(text=Bilgisayarnza virs
bulasms!)
Etiketimizi hazrladktan sonra paketleyip kargoya vermemiz gerekiyor. Grafik arayzn
278
kullancya ulasmas iin bu gerekli. Bunun iin xxx.pack() ifadesini kullanacagz. Buradaki
xxx yerine, bir st satrda hazrladgmz etiket iin kullandgmz ismi yazacagz. Mesela:
oyun.pack()
Btn bu yazdgmz kodlarn islevli hale gelebilmesi iin ise en sona mainloop() ifadesini
yerlestirmemiz gerekiyor.
Eger hazrladgmz pencerenin bir de baslg olsun istiyorsak title() adl metottan
yararlanyoruz.
Su
ana kadar yapabildigimiz tek sey bir pencere olusturup iine bir metin eklemek ve
pencerede basite bir baslk olusturmak. Ama tabii ki bir sre sonra bu da bizi skacaktr. Hem
sadece bu zellikleri grenerek heyecan verici arayzler hazrlamamz pek mmkn degil. En
fazla, arkadaslarmza ufak tefek sakalar yapabiliriz bu grendiklerimizle!
Yeri gelmisken, hazrladgmz program, simgesi zerine ift tklayarak nasl alstracagmz
grelim simdi. Geri daha nceki blmlerden hatrlyoruz bu isin nasl yaplacagn, ama biz
yine de tekrar hatrlatalm:
GNU/Linux kullanclar:
.py uzantl dosyamz hazrlarken ilk satra #!/usr/bin/env python ifadesini
mutlaka yazyoruz.
Kaydettigimiz .py uzantl dosyaya sag tklayarak zelliklere giriyoruz.
Burada izinler sekmesinde alstrlabilir ifadesinin yanndaki kutucugu
isaretliyoruz.
Tamam diyerek kyoruz.
Windows kullanclar:
Windows kullanclar .py uzantl dosyaya ift tklayarak program alstrabilir.
Ancak bu sekilde arkada bir de siyah DOS ekran alacaktr.
O DOS ekrannn almamas iin, kodlarmz barndran dosyamz .py uzants
ile degil .pyw uzants ile kaydediyoruz.
Dosya uzantsn .pyw olarak belirledikten sonra dosya zerine ift tklayarak
Tkinter programnz alstrabilirsiniz.
Windows kullanclar dosya kodlamas iin # -*- coding: cp1254 veya # -*coding: utf-8 -*- satrlarn kullanabilir.
Bylece artk programmzn simgesi zerine ift tklayarak arayzmz
alstrabiliriz.
18.3 Renkler
Dikkat ettiyseniz simdiye dek olusturdugumuz pencerelerde yazdgmz yazlar hep siyah
renkte. Tabii ki, siz olusturdugunuz pencereler iindeki metinlerin her daim siyah olmasn
istemiyor olabilirsiniz. ntanml renkleri degistirmek sizin en dogal hakknz. Tkinterle
alsrken renklerle oynamak olduka basittir. Renk islemleri Tkinterde birtakm ifadeler
18.3. Renkler
279
18.3.1 fg Seenegi
Diyelim ki pencere iine yazdgmz bir metni, daha fazla dikkat ekmesi iin krmz renkle
yazmak istiyoruz. Iste bu islem iin kullanmamz gereken sey fg seenegi. Bu ifade
Ingilizcedeki foreground (nplan, nalan) kelimesinin ksaltmas oluyor. Hemen bir rnek
verelim:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
pencere.title("Hata!")
etiket = Label(text = "Hata: Bilinmeyen Hata 404", fg="red")
etiket.pack()
mainloop()
Grdgnz gibi yaptgmz tek sey fg seenegini etiketin iine yerlestirmek. Burada
krmz renk iin kullandgmz kelime, Ingilizcede krmz anlamna gelen red szcg...
Yani insan dilinde kullanlan renkleri dogrudan Tkinterde de kullanabiliyoruz. Tabii bu
noktada biraz Ingilizce bilmek isinizi bir hayli kolaylastracaktr. Tkinterde
kullanabilecegimiz, Ingilizce renk adlarndan birka tanesini hemen sralayalm:
red = krmz
white = beyaz
black = siyah
yellow = sar
blue = mavi
brown = kahverengi
green = ye
sil
pink = pembe
Tkinterde kullanlabilecek renk adlar bunlarla snrl degil. Eger mevcut renk listesini
grmek isterseniz, su adrese bir bakabilirsiniz:
http://www.tcl.tk/man/tcl8.3/TkCmd/colors.htm. Tabii o listede sralanan renkler arasndan
istediginizi bulup karmak pek kolay degil. Ayn zamanda renklerin kendisini de gsteren bir
280
liste herhalde daha kullansl olurdu bizim iin. Neyse ki aresiz degiliz. Tkinter bize, renk
adlarnn yansra renk kodlarn kullanarak da yazlarmz renklendirebilme imkan veriyor.
Renk kodlarn bulmak iin su adresten yararlanabilirsiniz: http://html-color-codes.info
Burann avantaj, renklerin kendisini de dogrudan grebiliyor olmamz. Mesela orada
begendigimiz herhangi bir rengin zerine tkladgmzda, alttaki kutucukta o rengin kodu
grnecektir. Diyelim ki renk paletinden bir renk seip zerine tkladk ve alttaki kutucukta su
kod belirdi: #610B0B. Bu kodu kopyalayp kendi yazdgmz program iinde gerekli yere
yapstrabiliriz:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
pencere.title("Hata!")
etiket = Label(text = "Hata: Bilinmeyen Hata 404", fg="#610B0B")
etiket.pack()
mainloop()
Dogrudan renk adlar yerine renk kodlarn kullanmak daha kesin sonu verecektir. Ayrca
renk kodlar size daha genis bir renk yelpazesi sunacag iin epey isinize yarayacaktr.
Son olarak, yukardaki kodu snfl yap iinde kullanalm:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
class Uygulama(object):
def __init__(self):
self.etiket = Label(text="Hello", fg = "red")
self.etiket.pack()
pencere = Tk()
uyg = Uygulama()
mainloop()
18.3. Renkler
281
def araclar(self):
self.etiket = Label(text="Hata: Bilinmeyen Hata 404", fg="#610B0B")
self.etiket.pack()
pencere = Tk()
uyg = Uygulama()
mainloop()
Grdgnz gibi, bir nceki snfl rnekten pek fark yok. Tek yenilik fg seeneginin de
kodlar arasna eklenmis olmas.
18.3.2 bg Seenegi
Bu da Ingilizcedeki background (arkaplan, arkaalan) kelimesinin ksaltmas. Adndan da
anlaslacag gibi pencereye yazdgmz metnin arkaplan rengini degistirmeye yaryor.
Kullanm syle:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
pencere.title("Hata!")
etiket = Label(text = "Hata: Bilinmeyen Hata 404", bg="blue")
etiket.pack()
mainloop()
282
Son rnekte renk kodlar yerine renk adlarn kullandgmza dikkat edin.
Burada tahmin edebileceginiz gibi, Helvetica yaz tipini; 14 yaz boyutunu; bold ise
yaznn kaln olacagn gsteriyor. rnek bir kullanm syledir:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
etiket = Label(text="Merhaba Dostlar!", font="Times 15 italic")
etiket.pack()
mainloop()
Burada yaz tipi olarak Times; yaz boyutu olarak 15; yaz biimi olarak ise italic, yani
yatk biim setik. font seenegi ile birlikte kullanabilecegimiz ifadeler sunlardr:
italic = yatk
underline = alt izili
bold = kaln
overstrike = kelimenin st izili
Yaz tipi olarak neleri kullanabileceginizi, daha dogrusu kendi sisteminizde hangi
yaztiplerinin kurulu oldugunu ise syle grenebilirsiniz:
from Tkinter import *
import tkFont
pencere = Tk()
yazitipleri = list(tkFont.families() )
yazitipleri.sort()
for i in yazitipleri:
print i
283
Bu listede birden fazla kelimeden olusan yaz tiplerini gsterirken kelimeleri birlesik
yazmamz gerekiyor. Mesela DejaVu Sans semek iin DejaVuSans yazmamz lazm...
18.6 Imleler
Arayzlerinizi olustururken farkl imle sekilleri kullanmak da isteyebilirsiniz. Bunun iin
kullanacagmz seenek cursor. Mesela:
#!/usr/bin/env python # -- coding: utf-8 -from Tkinter import *
pencere = Tk()
etiket = Label(text=Deneme 1,2,3..., cursor=bottom_side) etiket.pack()
mainloop()
Burada, imleci pencere zerine getirdigimizde imlecin ters ok sekli aldgn grrz.
Kullanlabilecek imle isimleri iin su sayfaya bakabilirsiniz:
http://www.dil.univ-mrs.fr/~garreta/PythonBBSG/docs/Tkinter_ref.pdf
Burada 10. ve 11. sayfalarda hosunuza gidebilecek imle isimlerini seebilirsiniz. Bunun
dsnda yararlanabileceginiz baska bir kaynak da sudur:
http://www.tcl.tk/man/tcl8.4/TkCmd/cursors.htm
284
son bir zellikten bahsedip bu konuyu kapatalm. Grdgnz gibi olusturdugumuz bir
pencere ek bir abaya gerek kalmadan bir pencerenin sahip olabilecegi btn temel nitelikleri
tasyor. Buna pencerenin kullanc tarafndan serbeste boyutlandrlabilmesi de dahil. Ancak
baz uygulamalarda bu zellik anlamsz olacag iin (mesela hesap makinelerinde)
kullancnn pencereyi boyutlandrmasna engel olmak isteyebilirsiniz. Bu isi yapmak iin su
kodu kullanyoruz:
pencere.resizable(width=FALSE, height=FALSE)
285
Grdgnz gibi bu kodlar alstrldgnda ortaya kan pencere hibir sekilde boyutlandrma
kabul etmiyor...
Simdi
isterseniz yukarda verdigimiz kodlar snfl yap iinde nasl kullanacagmz grelim:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
class Uygulama(object):
def __init__(self):
self.etiket = Label(text="Hata!")
self.etiket.pack()
pencere = Tk()
pencere.resizable(width=FALSE, height=FALSE)
uyg = Uygulama()
mainloop()
Bylelikle Arayz Tasarm konusunun Temel Bilgiler ksmn bitirmis oluyoruz. Bir
sonraki blmde Tkinterde Pencere Aralarn (widgets) kullanmay grenecegiz. Ama
isterseniz yeni blme gemeden nce simdiye kadar grendigimiz hemen hemen btn
konular kapsayan bir rnek yapalm.
18.8 Tekrar
Simdiye
rnegimize geelim. Amacmz 1 ile 100 arasnda 6 tane rastgele say retmek. Yalnz
286
bu 6 saynn her biri benzersiz olacak. Yani 6 say iinde her say tek bir defa geecek. nce
kodlarmzn tamamn verelim:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
import random
liste = []
pencere = Tk()
pencere.geometry("200x50+600+460")
etiket = Label(fg="white", bg="#61380B",
font="Helvetica 12 bold")
etiket.pack()
for i in range(6):
while len(liste) != 6:
a = random.randint(1,100)
if a not in liste:
liste.append(a)
etiket["text"] = liste
mainloop()
Bu kodlar her alstrsmzda, 1 ile 100 arasnda, birbirinden farkl alt adet rastgele say
ekranda grnecektir. Tkintere iliskin kodlara gemeden nce, isterseniz yukarda
kullandgmz, rastgele say retmemizi saglayan Python kodunu biraz aklayalm:
Rastgele saylar retecegimiz iin ncelikle Pythonun random adl modln ie aktaryoruz.
Bu modl bu tr rastgele say retme islemlerinde kullanlr.
random modl iindeki randint() metodu bize, rnegin, 1den 100e kadar rastgele saylar
retme imkan saglar. Ancak random.randint(1, 100) dedigimiz zaman, bu kod 1den 100e
kadar rastgele tek bir say retecektir. Bizim amacmz alt adet rastgele say retmek.
Amacmz alt adet say retmek oldugu iin ncelikle for i in range(6): satr yardmyla alt
kez isletilecek bir dng olusturuyoruz. (Bunun mantgyla ilgili aklnzda spheler varsa, for
i in range(6): print Merhaba Dnya! komutunu vererek sphelerinizi giderebilirsiniz...) Bu
dng nihai olarak random.randint() fonksiyonunu alt kez alstracaktr. Bylelikle elimizde
alt adet say olmus olacak. Ancak retilen bu alt saynn hepsi birbirinden farkl olmayabilir.
Yani baz saylar birden fazla retilebilir. Dolaysyla 1, 5, 5, 7, 56, 64 gibi bir diziyle
basbasa kalabiliriz. Ama bizim amacmz alt saynn hepsinin birbirinden farkl olmas. O
yzden bunu saglayacak bir nlem almamz gerekiyor.
Bu bahsettigimiz nlemi if a not in liste: liste.append(a) satrlaryla alyoruz. Aradaki while
dngs baska bir ise yaryor. Onu birazdan aklayacagz.
if a not in liste: liste.append(a) satrlaryla, Eger random.randint(1, 100) komutu ile retilen
say liste iinde yer almyorsa bu sayy listeye ekle! emrini veriyoruz. Yani random.randint
18.8. Tekrar
287
ile her say retilisinde Pythonun bu sayy listeye eklemeden nce, listede bu saynn zaten
var olup olmadgn kontrol etmesini istiyoruz. Eger retilen say listede yoksa, liste.append()
komutu sayesinde saymz listeye eklenecek, yok eger retilen say listede zaten varsa o say
listeye alnmayacaktr. Ancak burada bir sorun kyor karsmza. Eger retilen say listede
zaten varsa, yukarda yazdgmz komut geregi o say listeye alnmayacak, bu durumda listede
6dan az say kalacaktr. Bizim, retilen saylarn ayn olmas durumunda random.randint
komutunun alty tamamlayana kadar tekrar tekrar say retmesini saglamamz gerekiyor.
Iste bu islemi yukardaki while dngs yardmyla yapacagz. while len(liste) != 6: satr ile
liste uzunlugunun 6ya esit olup olup olmadgn denetliyoruz. Yani Pythona su emri
veriyoruz. listenin uzunlugu 6ya esit olmadg srece random.randint(1,100) komutunu
isletmeye devam et!. Bylelikle, listedeki tekrar eden saylar yznden liste ierigi 6dan
kk oldugunda, bu while dngs sayesinde Python listeyi altya tamamlayana kadar
random.randint komutunu alstrmaya devam edecektir... if a not in liste: satr nedeniyle
zaten listede var olan saylar listeye ekleyemeyecegi iin de, benzersiz bir say bulana kadar
ugrasacak ve neticede bize alt adet, birbirinden farkl say verecektir...
Kodlarn Tkinter ile ilgili ksmna gelecek olursak... Esasnda yukardaki kodlar iinde geen
her satr anlayabilecek durumdayz. Simdiye
Etiketin text seeneginin bulunmadgna dikkat edin. Istersek yukardaki satrda text
seenegini, text = seklinde bos olarak da tanmlayabiliriz. Bu etiketi bu sekilde
tanmladktan sonra, programmz iinde baska bir yerde bu etiketin text seenegini, teki
zellikleriyle birlikte tek tek degistirebiliriz. Syle
ki:
etiket["text"]
etiket["fg"] =
etiket["bg"] =
etiket["font"]
= "www.istihza.com"
"red"
"black"
= "Verdana 14 italic"
Bu yapnn Pythondaki szlklere ne kadar benzedigine bir kez daha dikkatinizi ekmek
isterim. Bu yzden bu yapy grenmek sizin iin zor olmasa gerek.
Simdi
isterseniz yukarda verdigimiz rnegin snfl yap iinde nasl grnecegine bir
bakalm:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
import random
liste = []
288
class Uygulama(object):
def __init__(self):
self.araclar()
self.kodlar()
def kodlar(self):
for i in range(6):
while len(liste) != 6:
a = random.randint(1,100)
if a not in liste:
liste.append(a)
self.etiket["text"] = liste
def araclar(self):
self.etiket = Label(fg="white", bg="#61380B", font="Helvetica 12 bold")
self.etiket.pack()
pencere = Tk()
pencere.geometry("150x50+600+460")
uyg = Uygulama()
mainloop()
Grdgnz gibi, snfl yap iinde, kodlar ufak blmlere ayrarak incelenmelerini
kolaylastrms olduk. Artk rnegimizi verip aklamalarmz da yaptgmza gre, gnl
rahatlgyla bir sonraki blme geebiliriz.
18.8. Tekrar
289
BLM 19
Grdgnz gibi yukardaki kullanmda Label arac bir metnin pencere zerinde
grntlenmesini saglyor.
290
Dikkat ederseniz, Button() aracnn kullanm daha nce grdgmz Label aracnn
kullanmna ok benziyor. Burada da parantez iinde baz parametreler kullandk. text
parametresini zaten biliyoruz: Kullancya gstermek istedigimiz metni bu text parametresi
yardmyla belirliyoruz. Ayn parantez iinde grdgmz command parametresi ise dgme
zerine tklandgnda isletilecek komutu gsteriyor. Biz burada pencere.quit komutunu
vererek, dgmeye tklandgnda pencerenin kapatlmasn istedik. Dolaysyla bir satr iinde
yeni zellik grms oluyoruz:
Button: Kullanacagmz pencere arac (Ingilizce button kelimesi Trkede dgme
anlamna gelir).
command: Olusturdugumuz dgmeye tklandgnda alstrlacak komut
xxx.quit: Dgmeye tklandgnda pencerenin kapatlmasn saglayan komut.
Daha sonra gelen satrdaki ifade size tandk geliyor olmal: dugme.pack(). Tpk daha nce
etiket.pack() ifadesinde grdgmz gibi, bu ifade de hazrladgmz pencere aracnn kargoya
verilmek zere paketlenmesini saglyor.
En son satrdaki mainloop() ifadesinin ne ise yaradgn artk sylemeye bile gerek yok.
Yukarda bahsettigimiz command parametresi ok gzel isler yapmanz saglayabilir.
Mesela diyelim ki, olustur dgmesine basnca bilgisayarda yeni bir dosya olusturan bir
arayz tasarlamak istiyoruz. O halde hemen bu dsncemizi tatbik sahasna koyalm:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
def olustur():
dosya = open("deneme.txt", "w")
dugme = Button(text = "olu
stur", command=olustur)
291
dugme.pack()
mainloop()
Burada yaptgmz sey, ikinci bir dgme olusturmaktan ibaret. Olusturdugumuz dugme2
adl degisken iin de dugme2.pack ifadesini kullanmay unutmuyoruz.
Dgmelerin pencere stnde byle alt alta grnmesini istemiyor olabilirsiniz. Herhalde yan
yana duran dgmeler daha zarif grnecektir. Bunun iin kodumuza su eklemeleri yapmamz
gerekiyor:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
292
def olustur():
dosya = open("deneme.txt", "w")
dugme = Button(text = "olu
stur", command=olustur)
dugme.pack(side=LEFT)
dugme2 = Button(text = "k
s", command=pencere.quit)
dugme2.pack(side=RIGHT)
mainloop()
Hatrlarsanz nceki derslerimizden birinde, 1-100 aras saylar iinden rastgele alt farkl say
reten bir uygulama yazmstk. Artk Button adl pencere aracn grendigimize gre o
uygulamay birazck daha gelistirebiliriz. Mesela o uygulamaya bir dgme ekleyebilir, o
dgmeye basldka yeni saylarn retilmesini saglayabiliriz:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
import random
pencere = Tk()
pencere.geometry("300x50+600+460")
293
def kodlar():
liste = []
for i in range(6):
while len(liste) != 6:
a = random.randint(1,100)
if a not in liste:
liste.append(a)
etiket["text"] = liste
etiket = Label(text="Say retmek iin d
gmeye basn",
fg="white",
bg="#61380B",
font="Helvetica 12 bold")
etiket.pack()
dugme = Button(text="Yeniden",command=kodlar)
dugme.pack()
mainloop()
Burada, programda ana islevi gren kodlar kodlar() adl bir fonksiyon iine aldk. nk
Button pencere arac iindeki command seenegine atayabilmemiz iin elimizde bir
fonksiyon olmas gerekiyor. Dgmeye bastgmzda Tkinter, fonksiyon iindeki bu kodlar
isletecek. Dgmeye her basldgnda liste gelerinin yenilenebilmesi iin liste=[] satrn
fonksiyon iine alyoruz. Bylece dgmeye ilk kez basldgnda nce liste gesinin ii
bosaltlacak, ardndan alt adet say retilip etikete yazdrlacaktr. Bylelikle dgmeye her
bassmz yeni bir say dizisi olusturacaktr. Eger liste=[] satrn fonksiyon dsnda
tanmlarsak, dgmeye ilk bassmzda alt adet say retilecektir, ama ikinci kez dgmeye
bastgmzda, liste hala eski geleri tutuyor olacag iin etiket yenilenmeyecek. Dgmeye her
bassmzda eski saylar etikete yazdrlmaya devam edecektir. Bizim istedigimiz sey ise,
dgmeye her bassta yeni bir say setinin etikete yazdrlmas. Bunun iin liste=[] satrn
fonksiyon iine almamz gerekiyor.
Programmzn islevini yerine getirebilmesi iin kullancnn bir dgmeye basmas gerekiyor.
Bu yzden kullancya ne yapmas gerektigini sylesek iyi olur. Yani kullancmz dgmeye
basmaya ynlendirmemiz lazm. Bu amala etiketin text seenegine Say retmek iin
dgmeye basn seklinde bir uyar yerlestirdik. Programmz ilk kez alstrldgnda kullanc
ncelikle bu uyary grecek, bylelikle program kullanabilmek iin ne yapmas gerektigini
bilecektir. Belki bu kk programda ok belirgin olmayabilir, ama byk programlarda,
etiketler zerine yazdgmz ynergelerin ak ve anlaslr olmas ok nemlidir. Aksi halde
kullanc daha program deneyemeden bir kenara atabilir. Tabii biz byle olmasn istemeyiz,
degil mi?
Simdi
294
class Uygulama(object):
def __init__(self):
self.araclar()
def kodlar(self):
self.liste = []
for i in range(6):
while len(self.liste) != 6:
a = random.randint(1, 100)
if a not in self.liste:
self.liste.append(a)
self.etiket["text"] = self.liste
def araclar(self):
self.etiket = Label(text="Say retmek iin d
gmeye basn",
fg="white",
bg="#61380B",
font="Helvetica 12 bold")
self.etiket.pack()
self.dugme = Button(text="Yeniden", command = self.kodlar)
self.dugme.pack()
pencere = Tk()
pencere.geometry("300x50+600+460")
uyg = Uygulama()
mainloop()
Bu kodlar da nceki grdklerimizden ok farkl degil. Artk snfl bir Tkinter kodunun neye
benzedigini gayet iyi biliyoruz.
Her zamanki gibi ilk nce Tkinter modln agrarak ise basladk. Hemen ardndan da
pencere adn verdigimiz bos bir pencere olusturduk. Dedigimiz gibi, Entry() aracnn
kullanm daha nce szn ettigimiz pencere aralarnn kullanmna ok benzer. Dolaysyla
295
giris adn verdigimiz Entry() aracn rahatlkla olusturabiliyoruz. Bundan sonra yapmamz
gereken sey, tabii ki, bu pencere aracn paketlemek. Onu da giris.pack() satr yardmyla
hallediyoruz. Son darbeyi ise mainloop komutuyla vuruyoruz.
Grdgnz gibi, kullancya tek satrlk metin girme imkn veren bir arayz olusturmus
olduk. Isterseniz simdi bu pencereye birka dgme ekleyerek daha islevli bir hale getirelim
arayzmz. Mesela pencere zerinde program kapatmaya yarayan bir dgme ve
kullancnn yazdg metni silen bir dgme bulunsun:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
def sil():
giris.delete(0, END)
giris = Entry()
giris.pack()
dugme1 = Button(text = "KAPAT", command = pencere.quit)
dugme1.pack(side = LEFT)
L", command = sil)
dugme2 = Button(text = "SI
dugme2.pack(side = RIGHT)
mainloop()
Bu kodlar iinde bize yabanc olan tek ifade giris.delete(0, END). Bu komut, grnsnden de
anlaslacag gibi, giris degiskeninin ierigini silmeye yaryor. Parantez iindeki 0, END
ifadesi, metin kutusuna girilen kelimenin en basndan en sonuna kadar btn harflerin
silinmesi emrini veriyor. Eger 0, END yerine, mesela 2, 4 gibi bir ifade koysaydk, girilen
kelimenin 2. harfinden itibaren 4. harfine kadar olan ksmn silinmesi emrini vermis olacaktk.
Son bir alstrma yaparak bu arac da tamamlayalm:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
def olustur():
dosya = open("deneme.txt","w")
metin = giris.get()
dosya.write(metin)
giris = Entry()
giris.pack()
296
Burada da bize yabanc olan tek ifade giris.get(). Bu ifade Entry() pencere arac ile
kullancdan aldgmz metni elimizde tutup saklamamz saglyor. Burada bu ifadeyi nce
metin adl bir degiskene atadk, sonra da bu metin degiskeninin ierigini dosya.write(metin)
komutunun yardmyla bos bir dosyaya aktardk. Metin kutusunun ierigini barndran
deneme.txt isimli dosya /home klasrnzn altnda veya masastnde olusmus olmal.
Bir rnek daha yapalm...
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
import random
pencere = Tk()
def bas():
a = random.randint(1, 100)
giris.delete(0, END)
giris.insert(0, a)
giris = Entry(width=10)
giris.pack()
dugme = Button(text="bas", command=bas, width=2, height=0)
dugme.pack()
mainloop()
Grdgnz gibi, bu uygulama 1 ile 100 arasnda rastgele saylar seiyor. Aslnda yaptgmz
islem ok basit:
ncelikle Pythonun random adl modln agrdk. Daha nce de grdgmz gibi,
rastgele saylar seerken bize bu modl yardmc olacak. Ardndan da bu rastgele saylar
olusturup ekrana yazdrmamz saglayacak fonksiyonu olusturuyoruz. Bu fonksiyonda
ncelikle rastgele saylarn hangi aralkta olacagn belirleyip bunu a adl bir degiskene
atyoruz. Bylece rastgele saylar ekrana yazdrmak iin gereken altyapy olusturmus olduk.
Simdi
bu noktada eger bir nlem almazsak ekrana baslacak saylar yan yana sralanacaktr.
Yani mesela diyelim ki ilk rastgele saymz 3 olsun. Bu 3 says ekrana yazldktan sonra
ikinci rastgele say ekrana gelmeden nce bu ilk saynn ekrandan silinmesi gerekiyor. Btn
saylar yan yana ekrana dizilmemeli. Bunun iin kodumuza su satr ekliyoruz:
297
giris.delete(0, END)
Bu satr sayesinde, ilk say ekrana basldktan sonra ekrann 0. konumundan sonuncu
konumuna kadar btn her seyi siliyoruz. Bylelikle ikinci gelecek say iin yer ams
oluyoruz. Isterseniz yukardaki kodlar bu satr olmadan alstrmay bir deneyebilirsiniz.
Ondan sonra gelen satrn ne ise yaradgn anlamssnzdr: a degiskenini 0. konuma
yerlestiriyoruz. Fonksiyonumuzu bylece tamamlams olduk. Daha sonra normal bir sekilde
Entry ve Button adl pencere aralar yardmyla dgmelerimizi ve metin alanmz
olusturuyoruz. Burada baz yeni seenekler dikkatiniz ekmis olmal: Bunlar, width ve
height adl seenekler... width seenegi yardmyla bir pencere aracnn genisligini;
height seenegi yardmyla ise o aracn yksekligini belirliyoruz.
19.4 Frame()
Frame() Tkinter iinde bulunan snflardan biridir. Bu snf ayn zamanda bir pencere arac
(widget) olarak da kullanlabilir. Bir pencere arac olarak kullanldgnda bu snfn grevi,
pencere iindeki br pencere aralarn pencere iinde rahata konumlandrmay saglamaktr.
Bu aratan, ileride geometri yneticilerini (geometry managers) islerken daha ayrntl olarak
bahsedecegiz. Bu derste Frame() pencere aracnn temel olarak nasl kullanldgna dair birka
rnek vermekle yetinecegiz. Mesela su rnege bir bakalm:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
etiket = Label(text="A
sa
gdaki kutucu
ga e.posta adresinizi yaznz!")
etiket.pack()
giris = Entry()
giris.pack()
dugme = Button(text="Gnder", command=pencere.destroy)
dugme.pack()
mainloop()
Burada grdgnz gibi, gnder dgmesi hemen stndeki kutucuga ok yakn duruyor. Bu
arayzn daha iyi grnmesi iin bu iki pencere aracnn arasn biraz amak isteyebiliriz. Iste
Frame() arac byle bir ihtiya halinde isimize yarayabilir:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
298
pencere = Tk()
etiket = Label(text="A
sa
gdaki kutucu
ga e.posta adresinizi yaznz!")
etiket.pack()
giris = Entry()
giris.pack()
cerceve = Frame()
cerceve.pack()
dugme = Button(text="Gnder", command=pencere.destroy)
dugme.pack()
mainloop()
Grdgnz gibi, Frame() aracn giris ve dugme adl pencere aralarnn arasna
yerlestirdik. Bu kodlar alstrdgmzda, dgmenin azck da olsa asagya kaydgn
greceksiniz. Eger kayma orann artrmak isterseniz, pad seeneginden yararlanabilirsiniz.
Bu seenek, bir pencere aracnn, teki pencere aralar ile arasn amaya yaryor. pad
seenegi iki sekilde kullanlabilir: padx ve pady. Bu iki seenekten padx, x dzlemi
zerinde islem yaparken, pady ise y dzlemi zerinde islem yapyor. Yani:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
etiket = Label(text="A
sa
gdaki kutucu
ga e.posta adresinizi yaznz!")
etiket.pack()
giris = Entry()
giris.pack()
cerceve = Frame()
cerceve.pack(pady=5)
dugme = Button(text="Gnder", command=pencere.destroy)
dugme.pack()
mainloop()
299
Simdilik
300
BLM 20
301
onay_ka.pack()
mainloop()
Gayet gzel. Ama grdgnz gibi geler alt alta sralanrken hizal degiller. Dolaysyla gze
pek hos grnmyorlar. Eger istersek syle bir grnm verebiliriz onay kutularmza:
#!/usr/bin/python
#-*-coding=utf-8-*from Tkinter import *
pencere = Tk()
onay_el = Checkbutton(text="elma")
onay_el.pack(side=LEFT)
onay_sa = Checkbutton(text="salatalk")
onay_sa.pack(side=LEFT)
onay_do = Checkbutton(text="domates")
onay_do.pack(side=LEFT)
onay_ka = Checkbutton(text="karnbahar")
onay_ka.pack(side=LEFT)
mainloop()
geler byle yan yana dizildiklerinde fena grnmyorlar, ama biz yine de gelerin dzgn
sekilde alt alta dizilmesini isteyebiliriz. Burada geometri yneticilerinden biri olan place() adl
olan tercih edebiliriz. Simdi
bununla ilgili bir rnek grelim. Mesela bir tane onay kutusu
olusturup bunu en sola yaslayalm:
from Tkinter import *
pencere = Tk()
onay = Checkbutton(text="Kubuntu")
onay.place(relx = 0.0, rely = 0.1)
mainloop()
302
Dikkat ederseniz yukardaki btn onay kutularnn relx seenegi 0.0 iken, rely seenekleri
birer birer artms. Bunun nedeni, btn onay kutularn sola yaslayp hepsini alt alta dizmek
isteyisimiz. Bu rnek relx ve rely seeneklerinin nasl kullanlacag konusunda iyi bir fikir
vermis olmal. Eger bir kolaylk saglayacaksa, relxi stun, relyyi ise satr olarak
dsnebilirsiniz.
Simdi
Kubuntuyu 0.0 nolu stunun 0.1 nolu satrna; Debian da 0.4 nolu stunun 0.1 nolu
satrna yerlestirdik. Ayn sekilde Ubuntuyu 0.0 nolu stunun 0.2 nolu satrna; Windows
XPyi de 0.4 nolu stunun 0.2 nolu satrna yerlestirdik.
20.1. Checkbutton Pencere Arac
303
Eger olusturdugumuz bu onay kutularna biraz canllk katmak istersek, yani mesela kutunun
seili olup olmamasna gre baz isler yapmak istersek kullanmamz gereken baz zel kodlar
var... nce hemen yazmamz gereken ilk satrlar yazalm:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
Burada d=IntVar() satryla yaptgmz sey d adl bir degisken olusturup, bunun degeri
olarak IntVar() ifadesini belirlemek. Peki, bu IntVar() denen sey de ne oluyor?
IntVar(), Ingilizce Integer Variable (Say Degiskeni) ifadesinin ksaltmas. Bu ifade
yardmyla degisken olarak bir say belirlemis oluyoruz. Bunun dsnda Tkinterde
kullanacagmz, buna benzer iki ifade daha var: StringVar() ve DoubleVar()
StringVar() yardmyla karakter dizilerini; DoubleVar() yardmyla da ondalk saylar (kayan
noktal saylar floats) depolayabiliyoruz. Buraya kadar anlattklarmz biraz bulank gelmis
olabilir. Ama endiseye hi gerek yok. d=IntVar() satrnn hemen altndaki d.set(0) ifadesi pek
ok seyi aklga kavusturacak. O halde hemen bu satrn anlamn kavramaya alsalm.
Aslnda d=IntVar() ifadesi yardmyla basladgmz isi tamamlamamz saglayan satr bu
d.set(0) satr. Bunun yardmyla d=IntVar() ifadesinin degeri olarak 0 setik. Yani bu satr
bir onay kutusu iin yazdgmz dsnrsek, onay kutusunun degerini seili degil olarak
belirlemis olduk. Bu iki satrdan sonra olusturacagmz onay kutusu karsmza ilk ktgnda
isaretlenmemis olacaktr. Hemen grelim:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
d = IntVar()
d.set(0)
btn1 = Checkbutton(text="Kubuntu", variable=d)
btn1.place(relx=0.0,rely=0.1)
304
mainloop()
Burada dikkatimizi eken bir farkllk, btn1 adl onay kutusunun seenekleri arasna
variable adl bir seenegin girmis olmas. Bu seenegin islevini az ok anlams olmalsnz:
Yukarda belirledigimiz d=IntVar() ve d.set(0) ifadeleri ile Checkbutton pencere arac
arasnda baglant kuruyor. Yani bu seenek yardmyla pencerece aracna, degisken olarak
dyi kullan emrini veriyoruz.
Bu kodlar alstrdgmzda karsmza iinde bir onay kutusu bulunan bir pencere alr. Bu
penceredeki onay kutusu seili degildir. Isterseniz yukardaki kodlar iinde yer alan d.set(0)
ifadesini d.set(1) olarak degistirip kodlarmz yle alstralm:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
d = IntVar()
d.set(1)
btn1 = Checkbutton(text="Kubuntu", variable=d)
btn1.place(relx=0.0,rely=0.1)
mainloop()
Grdgnz gibi, bu defa olusan onay kutusu seili vaziyette. Eger yukardaki kodlar iindeki
d.set() satrn tamamen kaldrrsak, Tkinter varsaylan olarak d.set() iin 0 degerini
atayacaktr.
Gelin simdi bu kodlar biraz gelistirelim. Mesela penceremizde bir Entry() arac olsun ve onay
kutusunu setigimiz zaman bu Entry() aracnda bizim belirledigimiz bir cmle grnsn. Bu
kodlar iinde grecegimiz get ifadesine aslnda pek yabanc saylmayz. Bunu daha nceden
Entry() aracn kullanrken de grmstk. Bu ifade yardmyla bir degiskeninin degerini
sonradan kullanmak zere depolayabiliyoruz. Asagdaki rnegi dikkatle inceleyin:
#!/usr/bin/python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
# Onay kutusu iin bir de
gi
sken olu
sturuyoruz
v = IntVar()
# Bu de
gi
skene de
ger olarak "0" atayalm
v.set(0)
# br onay kutusu iin ba
ska bir de
gi
sken daha olu
sturuyoruz
305
z = IntVar()
# Bu de
gi
skene de "0" de
gerini atyoruz.
z.set(0)
# Bu kez bir karakter de
gi
skeni olu
sturalm
d = StringVar()
# Bu de
gi
skenin de
geri "Kubuntu" olsun.
d.set("Kubuntu")
# Bir tane daha karakter de
gi
skeni olu
sturalm
e = StringVar()
# Bunun da de
geri "Debian" olsun.
e.set("Debian")
#
Simdi onay kutularn seili hale getirdi
gimizde al
smasn
# istedi
gimiz komut iin bir fonksiyon olu
sturuyoruz:
def onay():
# E
ger "v" de
gi
skeninin de
geri "1" ise....
if v.get() == 1:
# d.get() ile "d" de
gi
skeninin de
gerini alyoruz...
giris.insert(0,"Merhaba %s kullancs" %d.get())
# Yok e
ger "z" de
gi
skeninin de
geri "1" ise...
elif z.get() == 1:
giris.delete(0, END)
# e.get() ile "e" de
gi
skeninin de
gerini alyoruz...
giris.insert(0,"Merhaba %s kullancs" %e.get())
# De
gi
skenlerin de
ger "1" de
gil, ba
ska bir de
ger ise..."
else:
giris.delete(0, END)
#"text" seene
ginin de
gerinin "d.get()" oldu
guna dikkat edin.
onay_pa = Checkbutton(text=d.get(), variable=v, command=onay)
onay_pa.place(relx = 0.0, rely = 0.1)
#"text" seene
ginin de
gerinin "e.get()" oldu
guna dikkat edin.
onay_de = Checkbutton(text=e.get(), variable=z, command=onay)
onay_de.place(relx= 0.0, rely= 0.2)
giris = Entry(width=24)
giris.place(relx = 0.0, rely=0.0)
mainloop()
306
Bu kodlar alstrdgmzda ekranda ikinci bir pencerenin daha aldgn grrz. Diyelim ki
bu ikinci pencerenin, bir dgmeye basldgnda almasn istiyoruz:
#!/usr/bin/python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
def ekle():
pencere2 = Toplevel()
btn_pen2 = Button(text="ekle", command=ekle)
btn_pen2.pack()
mainloop()
Grdgnz gibi pencere2nin alsn bir fonksiyona bagladk. Ardndan da ana pencere
zerinde btn_pen2 adl bir dgme olusturduk ve bu dgmeye command seenegi
yardmyla yukarda tanmladgmz fonksiyonu atayarak dgmeye baslnca ikinci pencerenin
almasn sagladk.
Eger alan ikinci pencere zerinde de baska dgmeler olsun istiyorsak su sekilde hareket
etmemiz gerekir:
#!/usr/bin/python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
def ekle():
pencere2 = Toplevel()
307
btn_pen = Button(pencere2,text="k
s", command=pencere2.destroy)
btn_pen.pack()
btn_pen2 = Button(pencere,text="ekle", command=ekle)
btn_pen2.pack()
mainloop()
Yine grdgnz gibi, ilk tanmladgmz ekle() fonksiyonu altnda bir dgme olusturduk.
Burada yeni bir durum dikkatinizi ekmis olmal. ekle() fonksiyonu altnda yeni
tanmladgmz dgmede ilave olarak text seeneginden nce bir pencere2 ifadesini
gryoruz. Bunu yapmamzn nedeni su: Elimizde pencere ve pencere2 adnda iki adet
pencere var. Byle bir durumda olusturulan pencere aracnn hangi pencere zerinde
gsterilecegini Tkintere anlatmamz gerekiyor. Sadece bir pencere varken pencereleri aka
belirtmeye gerek olmuyordu, ama eger birden pencere var ve siz olusturulan dgmenin hangi
pencere grntlenecegini belirtmezseniz, rnegin bizim durumumuzda Tkinter ekle adl
dgmeye her bassta otomatik olarak ana pencere zerinde ks adl bir dgme
olusturacaktr. Anladgnz gibi, eger aksi belirtilmemisse, pencere aralar otomatik olarak
ana pencere zerinde alacaktr.
Diyelim ki a, b, c ve d adlarnda drt adet penceremiz var. Iste hangi dgmenin hangi
pencerede grntlenecegini belirlemek iin bu zellikten faydalanacagz:
btn1
btn2
btn3
btn4
=
=
=
=
Button(a,
Button(b,
Button(c,
Button(d,
text="btn1")
text="btn2")
text="btn3")
text="btn4")
308
liste = Listbox()
liste.pack()
Grdgnz gibi, bu aracn da kullanm teki aralardan hi farkl degil. Isterseniz bu arac
bir de baglamnda grelim:
#!/usr/bin/python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
liste = Listbox()
liste.pack()
mainloop()
Bu haliyle pencerenin tamamn kapladg iin ok belirgin olmayabilir liste kutumuz. Ama
pencereye bir de dgme eklersek liste kutusu daha rahat seilebilir hale gelecektir:
#!/usr/bin/python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
liste = Listbox()
liste.pack()
btn = Button(text="ekle")
btn.pack()
mainloop()
Hatta simdiye kadar grendigimiz baska zellikleri kullanarak daha sk bir grnm de elde
edebiliriz:
#!/usr/bin/python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
liste = Listbox(bg="white")
liste.pack()
etiket = Label(text="#####################",
fg="magenta", bg="light green")
etiket.pack()
309
liste kutumuza baz geler ekleyelim. Bunun iin su basit ifadeyi kullanacagz:
liste.insert(END, "
ge 1")
Bunu bu sekilde tek basna kullanamayz. Hemen bu paracg yukardaki kod iine
yerlestirelim:
#!/usr/bin/python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
liste = Listbox(bg="white")
liste.insert(END,"
ge 1")
liste.pack()
etiket = Label(text="#####################",
fg="magenta", bg="light green")
etiket.pack()
btn = Button(text="ekle", bg="orange", fg="navy")
btn.pack()
etiket2 = Label(text="#####################",
fg="magenta", bg="light green")
etiket2.pack()
mainloop()
Grdgnz gibi, bu paracg, liste kutusunu tanmladgmz satrn hemen altna ekledik.
Biz liste kutumuza ayn anda birden fazla ge de eklemek isteyebiliriz. Bunun iin basite bir
for dngs kullanabiliriz:
gnulinux_dagitimlari = ["Pardus", "Debian", "Ubuntu", "PclinuxOS",
"TruvaLinux", "Gelecek Linux"]
for i in gnulinux_dagitimlari:
liste.insert(END, i)
310
Gayet gzel bir liste kutusu olusturduk ve listemizdeki geleri de rahatlkla seebiliyoruz.
Yalnz dikkat ettiyseniz ana pencere zerindeki ekle dgmesi su anda hibir ise yaramyor.
Tabii ki onu oraya bosu bosuna koymadk. Hemen bu dgmeye de bir islev atayalm. Mesela,
bu dgmeye basldgnda ayr bir pencere alsn ve kullancdan girdi alarak ana penceredeki
liste kutusuna eklesin. Tabii ki bu yeni alan pencerede de bir giris kutusu ve bir de islemi
tamamlamak iin bir dgme olsun. Hemen ise koyulalm:
#!/usr/bin/python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
liste = Listbox(bg="white")
liste.pack()
gnulinux_dagitimlari = ["Pardus", "Debian", "Ubuntu", "PclinuxOS",
"TruvaLinux", "Gelecek Linux"]
311
for i in gnulinux_dagitimlari:
liste.insert(END, i)
def yeni():
global giris
pencere2 = Toplevel()
giris = Entry(pencere2)
giris.pack()
btn2 = Button(pencere2, text="tamam",command=ekle)
btn2.pack()
def ekle():
liste.insert(END,giris.get())
giris.delete(0, END)
etiket = Label(text="#################", fg="magenta", bg="light green")
etiket.pack()
btn = Button(text="ekle", bg="orange", fg="navy", command=yeni)
btn.pack()
etiket2 = Label(text="#################", fg="magenta", bg="light green")
etiket2.pack()
mainloop()
Bu ksmda bildiginiz gibi nce liste adnda bir liste kutusu (Listbox) olusturduk. Liste
kutumuzun arkaplan rengini de beyaz olarak belirledik.
Ardndan da gnulinux_dagitimlari adnda bir liste olusturduk ve tek tek gelerini yazdk.
Hemen alt satrda bir for dngs yardmyla gnulinux_dagitimlari adl listedeki btn
geleri liste ad verdigimiz liste kutusu iine yerlestirdik:
312
def yeni():
global giris
pencere2 = Toplevel()
giris = Entry(pencere2)
giris.pack()
btn2 = Button(pencere2, text="tamam",command=ekle)
btn2.pack()
Burada yaptgmz is basit bir fonksiyon olusturmaktan ibaret. nce yeni() adl bir fonksiyon
olusturuyoruz. Ardndan pencere2 adyla ana pencereden ayr bir pencere daha
olusturuyoruz. Bu yeni pencere, ileride ekle tusuna bastgmzda almasn istedigimiz
pencere oluyor. Alt satrda, bu yeni pencere zerine yerlestirmek iin giris adl bir Entry()
pencere arac olusturuyoruz. Parantez iine pencere2 yazmay unutmuyoruz, nk bu
Entry() aracnn olusmasn istedigimiz yer ikinci pencere. Dikkat ettiyseniz fonksiyonu
tanmlarken global giris adl bir satr daha ekledik. Bu satrn amac, fonksiyon iindeki
giris adl Entry() aracn fonksiyon dsnda da kullanabilmek. nk bu Entry() arac bize
daha sonra da lazm olacak. Entry() aracna benzer sekilde bir de btn2 adyla bir dgme
olusturuyoruz. Bunu da ikinci penceremize yerlestiriyor, adn tamam koyuyor ve komut
olarak asagda tanmlayacagmz ekle() fonksiyonunu seiyoruz:
def ekle():
liste.insert(END,giris.get())
giris.delete(0, END)
Iste bu parada da ekle() adl bir fonksiyon olusturduk. Burada liste.insert ifadesi liste adl
liste kutusuna ekleme yapmamz saglyor. Parantez iindeki giris.get() ifadesi size tandk
geliyor olmal. nk ayn ifadeyi Entry() pencere aracn anlatrken de grmstk.
Hatrlarsanz bu ifade sayesinde Entry() aracna kullanc tarafndan girilen verileri daha sonra
kullanmak amacyla elimize tutabiliyorduk. Iste burada da bu ifade yardmyla giris adl
Entry() pencere aracnn ierigini alp liste adl liste kutusu iine yerlestiriyoruz. Alt
satrdaki giris.delete(0,END) ifadesi ise Entry() aracna kullanc tarafndan giris yapldktan
sonra kutunun bosaltlmasn saglyor:
etiket = Label(text="#################", fg="magenta", bg="light green")
etiket.pack()
btn = Button(text="ekle", bg="orange", fg="navy", command=yeni)
btn.pack()
etiket2 = Label(text="#################", fg="magenta", bg="light green")
etiket2.pack()
mainloop()
Bu son parada bilmedigimiz hibir sey yok. Normal bir sekilde etiket ad verdigimiz
Label() aracn tanmlyoruz. Burada Label() aracn ssleme amacyla nasl kullandgmza
dikkat edin. fg ve bg seeneklerini de nceki blmlerden hatrlyoruz. fg nplandaki
rengi; bg ise arkaplandaki rengi sememizi saglyor. magenta ve light green ise
kullanacagmz renklerin adlar oluyor. Bunun altnda ise basit bir Button() arac tanmlyoruz.
Ismini ve renklerini belirledikten sonra da command seenegi yardmyla yukarda
20.3. Listbox Pencere Arac
313
Grdgnz gibi giris bosken tamam tusuna basldgnda Veri Yok! ifadesi ekrana
yazdrlyor. Ancak burada syle bir problem var: Eger Veri Yok! ifadesi ekrana
yazdrldktan sonra kullanc bu ifadeyi silmeden bu ifadenin yanna bir seyler yazp
tamama basarsa Veri Yok! ifadesiyle birlikte o yeni yazdg seyler de listeye eklenecektir.
Bunu engellemek iin kodumuzu su hale getirebiliriz:
def ekle():
if not giris.get():
giris.insert(END,"Veri Yok!")
if not "Veri Yok!" in giris.get():
liste.insert(END, giris.get())
giris.delete(0,END)
Yani syle demis oluyoruz bu ifadelerle: Eger giris adl Entry arac bos ise, ara iinde Veri
Yok! ifadesini gster. Eger giris adl Entry arac iinde Veri Yok! ifadesi bulunmuyorsa,
liste adl Listbox aracna giris iindeki btn veriyi yazdr!
Liste kutumuza gelerimizi ekledik. Peki, bu geleri silmek istersek ne yapacagz?
Niyetimiz liste kutusundan ge silmek oldugunu gre en basta bir silme dgmesi
olusturmamz mantkl olacaktr:
btn_sil = Button()
btn_sil.pack()
314
Burada grdgnz gibi, silme islemi iin liste.delete ifadesini kullanyoruz. Parantez iindeki
ACTIVE ifadesi ise liste kutusu iinden bir seim yapp sil dgmesine basnca bu seili
genin silinmesini saglayacak. Yani aktif olan ge silinecek. Bu iki paray teki
komutlarla birlikte bir grelim bakalm:
#!/usr/bin/python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
liste = Listbox(bg="white")
liste.pack()
gnulinux_dagitimlari = ["Pardus", "Debian", "Ubuntu", "PclinuxOS",
"TruvaLinux", "Gelecek Linux"]
for i in gnulinux_dagitimlari:
liste.insert(END, i)
def yeni():
global giris
pencere2 = Toplevel()
giris = Entry(pencere2)
giris.pack()
btn2 = Button(pencere2, text="tamam",command=ekle)
btn2.pack()
def ekle():
if not giris.get():
giris.insert(END, "Veri Yok!")
if not "Veri Yok!" in giris.get():
liste.insert(END, giris.get())
giris.delete(0, END)
def sil():
liste.delete(ACTIVE)
etiket = Label(text="#################", fg="magenta", bg="light green")
etiket.pack()
btn = Button(text="ekle", bg="orange", fg="navy", command=yeni)
btn.pack()
btn_sil = Button(text="sil", bg="orange", fg="navy",command=sil)
btn_sil.pack()
315
Tabii ki, sil dgmesinin grnsn pencere zerindeki teki gelere uydurmak iin fg ve
bg seenekleri yardmyla ufak bir renk ayar yapmay da unutmadk.
Bylece bir pencere aracn daha bitirmis olduk. Gelelim sradaki pencere aracmza:
Simdi
Burada menu adl bir Menu pencere arac olusturduk. Ad menu olmak zorunda degil. Siz
istediginiz ismi kullanabilirsiniz. Ama tabii ki pencere aracmzn ad olan Menuyu
degistiremeyiz. Buraya kadar teki pencere aralarndan hibir fark yok.
Parantez iindeki pencere ifadesinden de anladgmz gibi, bu pencere aracn ana pencere
zerinde olusturuyoruz. Hatrlayacagnz gibi burada pencere diye ak ak belirtmesek de
Tkinter pencere aracmz otomatik olarak ana pencere zerinde olusturacaktr. Aslnda bu
satr yardmyla ana pencerenin en stnde, sonradan gelecek menler iin bir men ubugu
olusturmus oluyoruz:
pencere.config(menu=menu)
dosya = Menu(menu)
Burada config() metodu yardmyla ncelikle menu adl arac pencereye baglyoruz.
Parantez iindeki ilk menu ifadesi, tpk teki pencere aralarnda grdgmz text
ifadesi gibi bir seenek. ikinci menu ifadesi ise yukarda bizim Menu aracna kendi
verdigimiz isim. Bu isim herhangi bir kelime olabilirdi. Yani en basta mennn adn a
olarak belirleseydik, burada menu=a da diyebilirdik.
Ikinci satrda ise dosya adl baska bir Menu pencere arac daha olusturuyoruz. Hatrlarsanz
ilk Menu aracn olustururken parantez iine pencere yazarak arac pencereye baglamstk.
316
Bu kezse aracmz bir nceki menunn zerinde olusturuyoruz. Aslnda bu satr yardmyla
bir nceki asamada olusturdugunuz ara ubugu zerinde iner men (drop-down menu) iin
bir yer ams oluyoruz:
menu.add_cascade(label="Dosya", menu=dosya)
Simdi
Burada grdgmz ifadeler ise bir stte olusturdugumuz Dosya adl mennn alt
baslklarn olusturmamz saglyor. Burada add_command() metotlarnn dosya adl ara
ubuguna baglandgna dikkat edin. Bu satrlardan anladgnz gibi, Dosya adl menmzn
altnda A, Kaydet, Farkl Kaydet... ve ks gibi alt baslklar olacak.
Simdi
Bu kodlar alstrdgnzda gayet gzel bir pencere elde etmis olacaksnz... Yalnz dikkat
ettiyseniz, Dosyaya bastktan sonra alan alt mennn en stnde - gibi bir sey
gryoruz... Oraya tkladgmzda ise btn men ieriginin tek bir grup halinde toplanp ayr
20.4. Menu Pencere Arac
317
sin mantgn
Konu belki biraz karsk gelmis olabilir. Ama aslnda hi de yle degil. I
anlamak iin yukardaki kodlarda geen su satrlar bize epey yardmc olabilir:
menu = Menu(pencere)
dosya = Menu(menu, tearoff=0)
menu.add_cascade(label="Dosya",menu=dosya)
Dikkat ettiyseniz, nce Menu pencere aracn olusturuyoruz. Bu ara ilk olusturuldugunda,
parantez ii ifadeden anladgmz gibi, pencere adl ana pencere zerine baglanyor.
Ikinci satr vastasyla ikinci kez bir Menu pencere arac olustururken ise, parantez ii ifadeden
anlasldg gibi, olusturdugumuz meny bir nceki Menu pencere aracna baglyoruz.
nc satrda inen meny olustururken de, bunu bir nceki Menu pencere arac olan
dosyaya baglyoruz...
Menlere baska alt menler de eklerken bu mantk ok daha kolay anlaslyor. Syle
ki:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
menu = Menu(pencere)
pencere.config(menu=menu)
318
Grdgnz gibi, bu kez Menu pencere aracmz ilk olarak dosya adl ara zerine
baglyoruz. nk yeni pencere aracmz, bir nceki pencere arac olan dosyann zerinde
olusturulacak. Bir sonraki satrda add_command() metodunu kullanrken de alt menleri
yeni adl Menu pencere arac zerine baglyoruz. nk bu alt menler yeninin iinde yer
alacak...
Ayn sekilde eger Dosya baslgnn yanna bir de mesela Dzen diye bir seenek eklemek
istersek syle bir blm ekliyoruz kodlarmz arasna:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere= Tk()
menu= Menu(pencere)
pencere.config(menu=menu)
dosya= Menu(menu, tearoff=0)
menu.add_cascade(label="Dosya", menu=dosya)
dosya.add_command(label="A")
dosya.add_command(label="Kaydet")
dosya.add_command(label="Farkl Kaydet...")
dosya.add_command(label="k
s", command=pencere.quit)
yeni= Menu(dosya,tearoff=0)
dosya.add_cascade(label="Yeni",menu=yeni)
yeni.add_command(label="Metin Belgesi")
yeni.add_command(label="Resim Dosyas")
319
yeni.add_command(label="pdf dokman")
dosya2= Menu(menu, tearoff=0)
menu.add_cascade(label="Dzen",menu=dosya2)
dosya2.add_command(label="Bul")
mainloop()
kadar bir pencerenin sahip olmas gereken pek ok zelligi grdk. Hatta
pencerelerimize menler dahi ekledik. Btn bunlarn dsnda grenmemiz gereken ok
nemli bir pencere arac daha var. O da, Text() adl pencere aracdr. Bu ara sayesinde birden
fazla satr ieren metinler olusturabilecegiz. En basit haliyle Text() adl pencere aracn su
sekilde olusturabiliriz:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere= Tk()
metin= Text()
metin.pack()
mainloop()
Olusturdugumuz bu Text() arac pek ok islevi yerine getirebilecek durumdadr: Bu ara iine
su haliyle istedigimiz uzunlukta metin girebiliriz, klavye ve fareyi kullanarak metni
ynetebiliriz, hatta olusturdugumuz bu Text() aracn olduka basit bir metin editr olarak da
kullanabiliriz. Eger olusturdugumuz bu Text() arac iine ntanml olarak herhangi bir metin
yerlestirmek istersek su kodu kullanmamz gerekir:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere= Tk()
metin= Text(fg = "blue", font="Helvetica 13 bold")
metin.insert(END, "Srm 0.1.1")
metin.pack()
mainloop()
seenegi yardmyla metni mavi yaptk. font seenegi yardmyla ise yaz tipini, Helvetica,
13, koyu ve alt izili olarak belirledik.
Kodlarmz iinde kullandgmz metin.insert ifadesi de bize ntanml bir metin girme imkan
saglad. Parantez iinde belirttigimiz END ifadesi ntanml olarak yerlestirecegimiz metnin
pencere aracnn neresinde yer alacagn gsteriyor.
Yukarda verdigimiz kodu degistirerek isterseniz daha ekici bir grnm de elde
edebilirsiniz:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
a = "Srm 0.1.1"
metin = Text(bg="orange", fg = "blue", font="Helvetica 13 bold")
metin.insert(END, a.center(112, "*"))
metin.pack()
mainloop()
Eger bir metin iinden herhangi bir blm almak isterseniz kullanmanz gereken sey get
ifadesidir. Bu get ifadesinin nasl kullanldgn grelim simdi:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere= Tk()
metin = Text()
metin.pack()
metin.get(1.0,END)
mainloop()
Yukardaki rnegi sadece get ifadesinin nasl kullanldgn gstermek iin verdik. Su
haliyle
bu kod bizim beklentilerimizi karslayamaz. nk get ifadesi yardmyla metni aldk, ama
aldgmz bu metni kullanmamz saglayacak aralar henz penceremize yerlestirmedigimiz
iin get ifadesinin bize sagladg islevi kullanamyoruz. Simdilik
321
bakalm:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
metin = Text()
metin.pack()
metin.get(1.0,1.5)
mainloop()
Burada ise Text() aracnn birinci satr ve birinci stunundan, birinci satr ve besinci
stununa kadar olan aralktaki metin alnacaktr.
Simdi
Burada ncelikle Text() arac iindeki metnin tamamn alp (metin.get(1.0,END)) giris adl
pencere aracna yerlestiren (giris.insert(0,a)) bir fonksiyon olusturduk. Dikkat ederseniz
kullanm kolaylg asndan metin.get(1.0,END) ifadesini a adl bir degiskene atadk.
Daha sonra metin adl Text() aracmz ve btn adl Button() aracmz olusturduk. Button()
aracmza komut (command) olarak yukarda tanmladgmz fonksiyonu gstererek
Button ile fonksiyon arasnda iliski kurduk.
En sonunda da giris adl Entry aracmz tamamlayarak kodumuzu sona erdirdik.
322
Bu kodlar alstrdgmzda karsmza kan bos metin kutusuna herhangi bir sey yazp alttaki
dgmeye basnca, metin kutusunun btn ierigi dgmenin hemen altndaki kk metin
kutusuna islenecektir.
Simdi
Yukardaki kodlarda bir metni ve pencere aralarn nasl biimlendirdigimize dikkat edin.
Ayrca Pythonda karakter dizilerine ait bir metot olan center() yardmyla bir kelimenin
soluna ve sagna nasl baska karakterler yerlestirdigimizi inceleyin. Bu kodlar iinde
kendinize gre baz denemeler yaparak neyin ne ise yaradgn daha iyi anlayabilirsiniz.
Yukarda bahsettigimiz metnin koordinatlarn verme yntemi her zaman tercih edilecek bir
durum degildir. Ne de olsa kullanclarnzdan satr/stun saymasn bekleyemezsiniz!
Herhalde bu gibi durumlarda en iyi yntem seilen metnin alnmas olacaktr. Bunu da basite
su kodlar yardmyla yapyoruz:
metin.get("sel.first", "sel.last")
Burada sel.first ifadesi seimin baslang noktasn; sel.last ifadesi ise seimin bitis
noktasn gsteriyor.
Simdi
323
pencere= Tk()
def al():
a = metin.get("sel.first","sel.last")
metin2.insert(END, a)
Buraya kadar olan ksmda bir yenilik yok. Artk ezbere bildigimiz komutlar bunlar. Devam
ediyoruz:
kaydirma = Scrollbar(pencere)
kaydirma.pack(side=RIGHT, fill=Y)
Grdgnz gibi, Scrollbar adl pencere aracmz olusturup, bunu pack yneticisiyle
paketledik. pack() iindeki argmanlara dikkat edin. side=RIGHT ifadesi yardmyla
kaydrma ubugumuzu saga yaslarken, fill=Y ifadesi yardmyla da Y dzlemi zerinde (yani
yukardan asagya dogru) boylu boyunca uzatyoruz. Devam edelim:
metin = Text(yscrollcommand=kaydirma.set)
metin.pack()
324
Kaydrma ubugunu bir metin kutusu iinde kullanacagmz iin, Text pencere arac
vastasyla metin kutumuzu tanmlyoruz. Burada, yscrollcommand=kaydirma.set gibi bir
ifade kullandgmza dikkat edin. Bu ifade ile kaydrma islemini etkinlestiriyoruz. Simdi
son
darbeyi vurabiliriz:
kaydirma.config(command=metin.yview)
mainloop()
Burada kaydirma.config() satrn, metin aracn tanmladktan sonra yazmamz nemli. Eger
metin aracn tanmlamadan config satrn yazarsak komut satrnda hatalarn uustugunu
grrz...
Dilerseniz yukarda para para verdigimiz uygulamay bir de topluca grelim:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
kaydirma = Scrollbar(pencere)
kaydirma.pack(side=RIGHT, fill=Y)
metin = Text(yscrollcommand=kaydirma.set)
metin.pack()
kaydirma.config(command=metin.yview)
mainloop()
Bylece metin kutusuna yazdgmz yazlar asagya dogru uzadka sag tarafta bir kaydrma
ubugu grntlenecektir.
Peki, kaydrma ubugunun, ekrann alt tarafnda grnmesini istersek ne yapacagz? Yani
yukardaki rnekte yaptgmz gibi, asagya dogru giden metinleri degil de, yana dogru giden
metinleri kaydrmak istersek ne yapmalyz? ok kolay. Adm adm gidelim yine:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
...devam ediyoruz...
kaydirma = Scrollbar(pencere, orient=HORIZONTAL)
kaydirma.pack(side=BOTTOM, fill=X)
Grdgnz gibi, kaydrma ubugunun pozisyonunu belirlemek iin yeni bir seenekten
yararlanyoruz. Bu yeni seenegin ad orient. Buna vermemiz gereken deger ise
HORIZONTAL. Bu Ingilizce kelime Trkede yatay anlamna geliyor. Kaydrma
ubugumuz ekranda dsey degil, yatay vaziyette grnecegi iin bu seenegi kullandk.
20.6. Scrollbar Pencere Arac
325
Ayrca pack parametrelerine de dikkat edin. side seenegine BOTTOM degerini verdik.
nk kaydrma ubugumuzun ekrann alt tarafnda grnmesini istiyoruz. Bir nceki
rnekte, ubugun ekrann sagnda grnmesini istedigimiz iin side=RIGHT seklinde bir
kullanm benimsemistik (RIGHT kelimesi sag anlamna gelirken, BOTTOM kelimesi
dip, alt gibi anlamlara gelmektedir). Bu arada fill seeneginin degerinin de, bir nceki
rnegin aksine, X olduguna dikkat edin. nk bu defa kaydrma ubugumuzun x dzlemi
zerinde (yani soldan saga dogru) boylu boyunca uzanmas gerekiyor. Devam ediyoruz:
metin = Text(wrap=NONE, xscrollcommand=kaydirma.set)
metin.pack()
Simdi
Grdgnz gibi, burada da bir nceki rnekten farkl olarak xview ifadesini kullandk. Bir
nceki rnekte yview ifadesini kullanmstk. Bu farkn nedenini sylemeye gerek yok...
Gelin isterseniz bu paral rnegi bir araya getirelim:
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
kaydirma = Scrollbar(pencere, orient=HORIZONTAL)
kaydirma.pack(side=BOTTOM, fill=X)
metin = Text(wrap=NONE, xscrollcommand=kaydirma.set)
metin.pack()
kaydirma.config(command=metin.xview)
mainloop()
326
BLM 21
Tkinter arayz takm konusunda en fazla sikayet edilen sey; Tkinter ile yazlan uygulamalarn
irkin grnmesidir. Bu blmde bu sknty asmann baz yollarn gstermeye alsacagz.
Ayrca bu blmde, gzellik ile ilgili oldugunu dsndgm baska konulara da deginecegiz.
Mesela bu blmde, Tkinter uygulamalar iinde kullandgmz pencere aralarna nasl simge
yerlestirebilecegimizi de inceleyecegiz. Bu blm bir yandan da rnek uygulamalarla
zenginlestirilmeye alslacaktr. Yani konular anlatrken ufak program rnekleri zerinden
gitmeye alsacagz.
21.1 Tkinter
Programlarnn
stirmek
Degi
Renk
Semasn
Buna benzer btn uygulamalarmzda belli bir renk semas varsaylan olarak pencerelerimize
uygulanacaktr. Eger biz mdahale etmez isek, olusturacagmz btn pencereler ve
zerindeki pencere aralar tek bir renkte grnecektir. Ama eger istersek bu gidise bir dur
diyebiliriz. Bunu nasl yapabilecegimizi daha nceki derslerimizde de ksmen grmstk.
Mesela su seenekler bize yardmc oluyordu:
327
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
etiket = Label(text="rnek Uygulama", fg="white", bg="blue")
etiket.pack()
mainloop()
Grdgnz gibi, sadece tek bir pencere aracnn rengini degil, ayn zamanda btn bir
pencerenin rengini degistirdik. Bunu yapmamz saglayan sey de kodlar iinde kullandgmz,
pencere.tk_setPalette(#D0A9F5) satr oldu. Yani buradaki tk_setPalette() adl metodu
kullanarak btn pencerenin renk semasn degistirebildik. Bu tk_setPalette() komutu, Tk()
snfnn metotlarndan yalnzca bir tanesidir. Bu snfn bize hangi metotlar sundugunu
grmek iin Pythonun etkilesimli kabugunda su komutlar verebilirsiniz:
from Tkinter import *
dir(Tk())
Bu komutun kts olarak elde edilen liste alfabe srasna gre dizilmistir. Dolaysyla bu
listedeki tk_setPalette metodunu rahatlkla bulabilirsiniz...
Grdgnz gibi, Tk() snfnn bir ygn metodu var. Iste tk_setPalette() metodu da bunlardan
biri olup, Tkinter pencerelerinin renk semasn degistirmemizi saglyor.
Simdi
su rnege bakalm:
328
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
pencere.tk_setPalette("#D0A9F5")
etiket = Label(text="Hangi GNU/Linux Da
gtmn Kullanyorsunuz?")
etiket.pack(pady=10, padx=10)
liste = Listbox()
liste.pack(side=LEFT)
GNULinux = ["Debian", "Ubuntu", "Kubuntu", "RedHat"]
for i in GNULinux:
liste.insert(END, i)
dugme = Button(text="KAPAT", command=pencere.quit)
dugme.pack()
mainloop()
stirmek
21.1. Tkinter Programlarnn Renk Semasn
Degi
329
Grdgnz gibi, farkl renkte olmasn istedigimiz pencere aralarnn renklerini, daha nce
grendigimiz seenekler yardmyla ak ak belirtiyoruz. Tabii sizin benden daha zevkli renk
kombinasyonlar seeceginizi tahmin ediyorum.
Bylelikle bir Tkinter programnn renk semasn nasl degistirecegimizi grenmis olduk. Bir
sonraki blmde Tkinter uygulamalar zerinde resimleri/simgeleri nasl kullanabilecegimizi
grecegiz. Neticede resimler ve simgeler de bir program gzellestiren gelerdir.
Bylelikle gerekli btn modlleri ie aktarms olduk. Burada ImageTk adl modl de ie
aktardgmza dikkat edin. Devam ediyoruz:
pencere = Tk()
simge = ImageTk.PhotoImage(file="simge.png")
Yukardaki kodlar yardmyla nce bir pencere olusturduk her zamanki gibi. Ardndan da,
programn en basnda ie aktardgmz ImageTk adl modln PhotoImage adl metodundan
ve file adl seeneginden yararlanarak, bilgisayarmzdaki simge.png adl dosyay
programmz iinde kullanlabilir hale getirdik. Dikkat edin, kullandk, diyemiyoruz;
kullanlabilir hale getirdik, diyoruz. Yani kabaca ifade etmek gerekirse, bu sekilde bir
resim nesnesi olusturmus oluyoruz. Devam edelim:
dugme = Button(text="Resim1", image=simge, compound="top")
dugme.pack()
mainloop()
Burada bildigimiz sekilde, Button pencere aracn kullanarak bir dgme olusturduk. Ama
burada bilmedigimiz birka sey var. Hemen anlatalm: ncelikle image adl yeni bir
seenek gryoruz kodlarmz arasnda. Buraya, yukarda kullanlabilir hale getirdigimiz
resim nesnesini yerlestiriyoruz. Bu seenegin ardndan, compound adl baska bir seenek
daha geliyor. Bu da text ve image seenekleri ile tanmlanan gelerin pencerede nasl
grnecegini belirliyor. Burada kullandgmz top degeri, image seenegiyle gsterilen
genin, text seenegi ile gsterilen genin stnde yer alacagn ifade ediyor. Bu compound
seenegi drt farkl deger alabilir:
330
Bylece Tkinterde resimleri ve metinleri bir arada nasl kullanacagmz grenmis olduk.
Simdi
=
=
=
=
ImageTk.PhotoImage(file="simge1.png")
ImageTk.PhotoImage(file="simge2.png")
ImageTk.PhotoImage(file="simge3.png")
ImageTk.PhotoImage(file="simge4.png")
331
etiket.pack()
dugme1 = Button(cerceve2, text="Resim1", image=simge1, compound="top")
dugme1.grid(row=3, column=0, padx=6)
dugme2 = Button(cerceve2, text="Resim2", image=simge2, compound="top")
dugme2.grid(row=3, column=3, padx=6)
dugme3 = Button(cerceve2, text="Resim3", image=simge3, compound="top")
dugme3.grid(row=3, column=6, padx=6)
dugme4 = Button(cerceve2, text="Resim4", image=simge4, compound="top")
dugme4.grid(row=3, column=9, padx=6)
Tabii bu programn dzgn alsmas iin resimlerinizle program dosyasn ayn klasre
koymay unutmuyorsunuz. Eger resimlerle program dosyas ayr klasrlerde duracaksa simge
gelerini belirlerken resimlerin bulundugu klasr adlarn tam olarak yazmaya dikkat
etmelisiniz.
Burada dgmeleri konumlandrmak iin pack() geometri yneticisi yerine grid() adl geometri
yneticisini kullandgmza dikkat edin. geleri bu sekilde sralamak iin grid() yneticisi
daha uygundur. Ayrca yukardaki kodlarda iki farkl Frame olusturdugumuza da dikkat
edin. Label adl pencere aracmz bir Frame zerine, geri kalan pencere aralarmz
(yani dgmelerimizi) ise teki Frame zerine yerlestirdik. Iki farkl Frame kullanmamz
sayesinde ayn program iinde hem grid() hem de pack() adl geometri yneticilerini bir arada
kullanma imkan elde ettik. Iki farkl Frame kullanmamz ayn zamanda bize, pencere
aralarmz daha zgr bir sekilde konumlandrma imkan da saglad. Ayrca grid()
yneticisinin padx seenegini kullanarak pencere aralarnn birbirlerine olan uzaklklarn
da ayarlayabildik. Yukardaki kodlarla ilgili olarak anlamadgnz noktalar olmas durumunda
bana nasl ulasabileceginizi biliyorsunuz.
Bylelikle bu konuyu da bitirmis olduk. Bir sonraki blmde Tkinter ile yazdgmz pencere
aralarna nasl ipucu metni (tooltip) ekleyecegimizi grecegiz.
332
Burada normal bir sekilde, penceremizi tanmladk. Bunun yannda, bir adet etiket, bir adet de
dgme olusturduk. Yeni bir sey yok... Devam edelim:
wckToolTips.register(dugme, "Program kapat")
mainloop()
Iste wckToolTips modl burada devreye giriyor. Bu modln register() adl metodunu
kullanarak, dugme adl pencere aracnn zerine fare ile geldigimizde ekranda grnmesini
istedigimiz ipucu metnini olusturuyoruz. Burada ipucu metnimiz su: Program kapat
Programmz btnyle bir grelim bakalm:
333
Grdgnz gibi, dugmenin zerine fare ile geldigimizde ipucu metnimiz ekranda
grnyor... Iste Tkinterde ipucu metinlerini kullanmak bu kadar kolaydr. Kendi yazdgnz
programlarda bu modl kullanarak, programnz kullanclar asndan daha cazip ve
anlaslr bir hale getirebilirsiniz. Gelin isterseniz bununla ilgili bir rnek daha yapalm:
# -*- coding: utf-8 -*from Tkinter import *
import wckToolTips
import time
pencere = Tk()
etiket = Label(text="Saat 17:00'da randevunuz var!")
etiket.pack(expand=YES, fill=BOTH)
def saat(pencere_araci, fonksiyon):
return "
Su anda saat: %s"%time.strftime("%H:%M:%S")
dugme = Button(text="Tamam", command=pencere.destroy)
dugme.pack(expand=YES)
wckToolTips.register(pencere, saat)
mainloop()
Burada ipucu metnimizi dogrudan pencerenin kendisine atadk. Bylece fare ile pencere
zerine geldigimizde o an saatin ka oldugu ekranda grnecektir... Ayrca burada register()
metoduna argman olarak bir fonksiyon atadgmza dikkat edin. Yukarda yazdgmz kodlar
syle yazarsak ne olur peki?
# -*- coding: utf-8 -*from Tkinter import *
334
import wckToolTips
import time
pencere = Tk()
etiket = Label(text="Saat 17:00'da randevunuz var!")
etiket.pack(expand=YES, fill=BOTH)
dugme = Button(text="Tamam", command=pencere.destroy)
dugme.pack(expand=YES)
wckToolTips.register(pencere, "
Su anda saat: %s" \
%time.strftime("%H:%M:%S"))
mainloop()
Bu sekilde, programmz yine alsr ve hatta saatin ka oldugunu ekranda ipucu metni olarak
da gsterir. Ama bir farkla: Bu yazm seklinde ekranda grnen saat duragan olacaktr. Yani
program kapatlp tekrar alana kadar hep ayn saati gsterecektir. Ama register() metoduna
bir nceki rnekte oldugu gibi, bir fonksiyon atarsak saat devinecek, yani pencere zerine
ikinci kez geldigimizde ipucu metni saati gncellenmis olarak verecektir.
Bu son kodlarda, ayrca pack() geometri yneticisinin expand ve fill seeneklerini
kullanarak pencere boyutlandrmalar srasnda pencere aralarnn uzayp ksalmasn
sagladk. Bu kodlar bir de bu seenekler olmadan alstrrsanz ne demek istedigim daha
bariz bir sekilde ortaya kacaktr.
Son olarak, yukardaki kodlarda, saat() adl fonksiyonun iki argman aldgna dikkat edin. Bu
fonksiyonu argmansz olarak yazarsak programmz alssa da ipucu metni
grntlenmeyecektir. Byle bir durumda ipucu metninin grntlenmemesine yol aan
hatay komut satr ktlarndan takip edebilirsiniz.
335
BLM 22
Nasl Yaplr?
def kaydet():
dosya = open("isimler_python.txt","a")
veri = giris.get()
veri = unicode.encode(unicode(veri),"utf8")
dosya.write(veri+"\n")
dosya.close()
etiket["text"] = etiket["text"] + u"%s dosyaya ba
saryla eklendi\n" %giris.
giris.delete(0, END)
dugme = Button(text="Tamam", command=kaydet)
dugme.pack()
mainloop()
336
def kaydet(event=None):
dosya = open("isimler_python.txt", "a")
veri = giris.get()
veri = unicode.encode(unicode(veri), "utf8")
dosya.write(veri+"\\n")
dosya.close()
etiket["text"] = etiket["text"] + u"%s dosyaya ba
saryla eklendi\n"%giris.ge
giris.delete(0, END)
dugme = Button(text="Tamam", command=kaydet)
dugme.pack()
pencere.bind("<Return>", kaydet)
mainloop()
kaydet() fonksiyonuna ekledigimiz event parametresi zorunlu bir adlandrma degildir. Hatta
oraya kendi isminizi dahi yazdgnzda programn dzgn alstgn greceksiniz. Ancak
22.1. Tkinterde Fare ve Klavye Hareketleri (Events and Bindings)
337
oraya bir parametre yazacagnz zaman herhangi bir kelime yerine event ifadesini
kullanmanz tavsiye ederim. nk event tpk snflardaki self gibi kemiklesmistir.
Burada dikkat etmemiz gereken iki sey var: Birincisi, o fonksiyonu parametresiz brakmamak;
ikincisi, parametreye varsaylan deger olarak None vermek. Eger bu None degerini
vermezseniz, kullanc ENTER tusuna bastgnda program alsr, ama Tamam dgmesine
bastgnda alsmaz. nk; Tkinter event parametresinin degerini command=kaydet
seklinde gsterdigimiz koda otomatik olarak atamayacaktr. Bu yzden, oraya varsaylan
deger olarak None yazmazsak, kaydet() fonksiyonunun bir adet argman almas
gerektigine dair bir hata alrz.
Kodlarmza yaptgmz ikinci ekleme, bind() fonksiyonudur. Burada dikkat etmemiz gereken
birka sey var. ncelikle bu bind() fonksiyonunu pencere ile birlikte kullandgmza dikkat
edin. Bu satrla aslnda Tkintere su komutu vermis oluyoruz:
Ey Tkinter! pencere seili iken, yani etkinken, kullanc RETURN dgmesine (veya baska
bir syleyisle ENTER dgmesine) bastgnda kaydet() adl fonksiyonu alstr!
Artk kullancmz, kutucuga bir isim yazp ENTER dgmesine bastgnda, yazdg isim
dosyaya eklenecektir.
Grdgnz gibi, eger klavyedeki ENTER dgmesini baglamak istiyorsak, kullanmamz
gereken ifade <Return>. Peki, baska hangi ifadeler var? Mesela ESCAPE iin bir rnek
verelim. Yukardaki kodlara ufack bir ekleme yapyoruz:
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
etiket = Label(text="A
sa
gdaki kutucu
ga adnz yazp \
Tamam d
gmesine basn!\n")
etiket.pack()
giris = Entry()
giris.pack()
def kaydet(event=None):
dosya = open("isimler_python.txt", "a")
veri = giris.get()
veri = unicode.encode(unicode(veri), "utf8")
dosya.write(veri+"\\n")
dosya.close()
etiket["text"] = etiket["text"] + u"%s dosyaya ba
saryla eklendi\n"%giris.ge
giris.delete(0, END)
dugme = Button(text="Tamam", command=kaydet)
dugme.pack()
pencere.bind("<Return>", kaydet)
pencere.bind("<Escape>", sys.exit)
338
mainloop()
Klavyedeki harfleri pencere aralarna baglamak iin ise dogrudan o harfin adn
kullanabiliriz. Mesela bir islemin, f harfine basldgnda gereklesmesini istersek,
yazmamz gereken ifade, f olacaktr. Bunun, <f> degil, sadece f seklinde olduguna
dikkat edin. Tabii burada, Trkeye zg harfleri kullanmamaya dikkat ediyoruz...
Klavye hareketlerini baglamay grendik. Peki ya fare hareketlerini nasl baglayacagz? O da
ok basittir. Burada da yine bind() fonksiyonundan yararlanacagz. Gelin isterseniz syle bir
uygulama yazalm:
339
Yukardaki uygulamay alstrp pencere zerinde herhangi bir yere farenin sol tusu ile
tkladgmzda, tkladgmz noktann koordinatlar (x ve y dzlemine gre) kutucuklar iinde
grnecektir.
Bu kodlar biraz aklayalm:
Kodlar arasnda grdgnz anchor ifadesi, pack() adl pencere yneticisinin
seeneklerinden biridir. Bu seenek, ilgili pencere aracnn pencere zerinde bir noktaya
apa atmasn saglar (Ingilizce anchor kelimesi Trkede apa atmak, demir atmak
gibi anlamlara gelir...). Bu seenek drt farkl deger alabilir:
N : Kuzey anlamna gelen North kelimesinin ksaltmasdr. Pencere aracnn
kuzey ynne sabitlenmesini saglar.
S : Gney anlamna gelen South kelimesinin ksaltmasdr. Pencere aracnn
gney ynne sabitlenmesini saglar.
W : Bat anlamna gelen West kelimesinin ksaltmasdr. Pencere aracnn bat
ynne sabitlenmesini saglar.
340
341
342
giris.bind("<Key>", silemezsin)
mainloop()
Buradaki kodlara gre, eger kullanc BACKSPACE veya DELETE tuslarna basarak yazdg
yazy silmek isterse, beklentilerinin aksine bu tuslar alsmayacaktr. Burada return break
adl zel bir ifadeden yararlanyoruz. Bu ifade, normal sartlarda gereklesmesi
engellenemeyecek olan islemlerin etkisizlestirilmesini saglayan zel bir kullanmdr. rnegin
yukardaki silemezsin() fonksiyonunu bir de syle yazmay deneyin:
def silemezsin(event=None):
if event.keysym:
return "break"
Bu sekilde, kullanc Entry arac iine hibir sekilde yaz yazamayacaktr. Dolaysyla
yukardaki fonksiyonun adn silemezsin yerine yazamazsn koymak daha uygun
olacaktr!
Son olarak, bu konuyla ilgili oldugu iin, focus_set() fonksiyonundan da bahsetmekte fayda
var. Bu fonksiyon, pencere aralarn etkin hale getirmemizi saglyor. Bu blmn en basnda
verdigimiz rnegi hatrlyorsunuz. Kullanc bir kutucuga adn giriyor ve girdigi bu ad bir
dosyaya yazdrlyordu. O rnegi isterseniz yeniden alstrn. Greceginiz gibi, kutucuga bir
sey yazabilmek iin ncelikle o kutucuga bir kez tklamak gerekiyor. Yani aslnda
programmz ilk aldgnda o kutucuk etkin degil. Bizim onu etkin hale getirmek iin zerine
bir kez tklamamz gerekiyor. Ama istersek, o kutucugun alsta etkin hale gelmesini
saglayabiliriz. Bylece kullanclarmz dogrudan kutuya yazmaya baslayabilirler:
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
etiket = Label(text="A
sa
gdaki kutucu
ga adnz yazp \
Tamam d
gmesine basn!\n")
etiket.pack()
giris = Entry()
giris.pack()
giris.focus_set()
def kaydet():
dosya = open("isimler_python.txt", "a")
veri = giris.get()
veri = unicode.encode(unicode(veri), "utf8")
dosya.write(veri+ "\n")
dosya.close()
etiket["text"] = etiket["text"] + u"%s dosyaya \
ba
saryla eklendi\n"%giris.get()
giris.delete(0,END)
343
Grdgnz gibi, klavyedeki ENTER tusunu baz fonksiyonlara bagladgmz halde, program
alstrdgmzda ENTER tusuna basmak hibir ise yaramyor. Bunun nedeni, programmz ilk
aldgnda pencerenin kendisi hari hi bir pencere aracnn etkin olmamasdr. Bagladgmz
tuslarn alsabilmesi iin ncelikle ilgili pencere aralarnn etkinlestirilmesi gerekiyor:
# -*- coding: utf-8 -*from Tkinter import *
from sys import exit
344
pencere = Tk()
etiket = Label(text="Programdan kmak istedi
ginize emin misiniz?")
etiket.pack()
cerceve = Frame()
cerceve.pack()
def sagol(event=None):
yeni = Toplevel()
etiket = Label(yeni, text="Te
sekkrler... :)")
yeni.bind("<Return>", exit)
etiket.pack()
kapat = Button(cerceve, text="Evet", command=pencere.destroy)
kapat.grid(row=1, column=0)
kapatma = Button(cerceve, text="Hayr", command=sagol)
kapatma.grid(row=1, column=1)
kapat.focus_set()
kapat.bind("<Return>", exit)
kapatma.bind("<Return>", sagol)
mainloop()
Buradaki tek fark, kodlar arasna kapat.focus_set() ifadesinin eklenmis olmas. Bu ifade
sayesinde, programmz ilk aldgnda odak Evet dgmesi zerinde olacaktr. Dolaysyla
ENTER tusuna bastgmzda, bu dgmenin bagl oldugu fonksiyon alsacak ve programmz
kapanacaktr. Program akken, klavyedeki TAB tusuna basarak odag degistirebiliriz. Mesela
programmz ilk alstrdgmzda odak Evet dgmesi zerinde olacag iin, TAB tusuna bir
kez bastgmzda odak Hayr dgmesine geecektir. Bu haldeyken ENTER tusuna basarsak,
Hayr dgmesinin bagl oldugu fonksiyon alsacaktr.
Isterseniz konuyu kapatmadan nce basit bir oyun denemesi yapalm:
nce http://www.akcilaclama.com/images/sinek.ilaclama.jpg adresine gidip oradaki sinek
resmini bilgisayarnza indirin. Adn da sinek.jpg koyun. Daha sonra su kodlar yazn:
# -*- coding: utf-8 -*from Tkinter import *
import random, ImageTk
pencere = Tk()
pencere.geometry("600x600")
pencere.tk_setPalette("white")
def yakala(event=None):
k = random.randint(0,550)
v = random.randint(0,550)
345
print k, v
dugme.place(x=k, y=v)
simge = ImageTk.PhotoImage(file="sinek.jpg")
dugme = Button(image=simge, command=yakala, relief="flat")
dugme.place(x=1, y=0)
dugme.bind("<Enter>", yakala)
mainloop()
Grdgnz gibi, enter ifadesi kullancnn ENTER tusuna bastg anlamna gelmiyor. O is
iin Return ifadesini kullanyoruz. Fazlasyla birbirine karstrlan bir konu oldugu iin
zellikle vurgulama geregi duyuyorum.
Burada sinegi yakalama ihtimaliniz var. Eger randomun rettigi saylar birbirine yakn olursa
sinek elinizden kaamayabilir.
Bylelikle bu konuyu da bitirmis olduk. Her ne kadar baslangta karskms gibi grnse de
aslnda hem ok kolay hem de ok keyifli bir konudur fare ve klavye hareketleri konusu. Bu
yazy birka kez gzden geirerek baz noktalarn tam olarak zihninize yerlesmesini
saglayabilirsiniz.
Isterseniz bu liste kutusunun daha belirgin olmas iin buna birka ge ekleyelim:
from Tkinter import *
pencere = Tk()
listekutusu = Listbox()
listekutusu.pack()
dagitimlar = ["Debian", "Ubuntu", "Mandriva", "Arch", "Gentoo"]
for i in dagitimlar:
listekutusu.insert(0, i)
346
mainloop()
347
mainloop()
Liste kutusuna grev atama islemini bu satr yardmyla yaptk. Kullanc listekutusu iindeki
herhangi bir geye ift tkladg zaman, tklanan geyle ilgili bilgi veriyoruz. Listbox() adl
pencere aracnn kendisine ait bir command seenegi olmadg iin, istedigimiz islevi, daha
nceki derslerde grdgmz bind metodu yardmyla hallediyoruz. Burada
Double-Button-1 ifadesini kullandgmza dikkat edin. Bu ifade farenin sol tusuna ift
tklama hareketini temsil ediyor. Liste kutularndaki gelere islev atamak istedigimiz zaman
en dogru sonucu Double-Button-1 ile elde ediyoruz. teki seenekler her zaman istedigimiz
islevi yerine getirmeyebilir.
Hale Getirmek
Tkinterde standart bir pencerenin nasl olusturulacagn biliyoruz:
pencere = Tk()
Bu sekilde bir pencere olusturdugumuzda, elde ettigimiz pencere, bir pencerenin sahip olmas
gereken btn zellikleri tasr. Dolaysyla pencereyi kapatmak, pencereyi kltmek veya
pencereyi asag indirmek istedigimizde zel olarak herhangi bir kod yazmamza gerek yoktur.
Pencere baslg zerindeki arp, kare ve eksi dgmelerine tklayarak gerekli islevleri yerine
getirebiliriz. Normal sartlar altnda bu tr zelliklerin olmadg bir pencere pek bir isimize
yaramaz. Ama bazen pencerenin srkleme ubugu dahil hi bir zelliginin olmamasn
isteyebiliriz. Iste bu blmde bu istegimizi nasl yerine getirebilecegimizi grecegiz. Simdi
Burada overrideredirect kelimesinin yazlsna azami zen gstermek gerekir. Uzun bir
kelime oldugu iin yanls yazlma olaslg olduka yksektir.
Kodlarmzn son hali syle oldu:
#!/usr/bin/env python
#-*- coding: utf-8 -*-
348
Yalnz bu kodlar mutlaka komut satrndan alstrn. Kesinlikle yazdgnz betigin zerine
ift tklayarak alstrmay denemeyin.
Simdi
komut satrn kullanarak betigimizi alstryoruz. Grdgnz gibi, bombos bir kare
elde ettik. Bu pencerenin, kendisini kapatmamz saglayacak bir dgmesi bile yok. Simdi
349
pencerelerle neler yaplabilecegine dair ufak bir rnek gstermekti... Yukardaki kodlar ise
yarar bir hale getirmek iin zerinde biraz alsmanz gerekir.
Hatrlarsanz, nceki blmlerden birinde Pencere Aralarna Ipucu Metni Eklemek baslkl
bir konu islemistik. Orada gsterdigimiz wcktooltips.py adl modlde de bu
overrideredirect zelliginden yararlanlyor. Su
adrese gidip wcktooltips modlnn
kaynagna baktgmzda kodlar arasnda self.popup.overrideredirect(1) satrn gryoruz.
Yani Fredrik Lundh ipucu penceresini olusturmak iin baslksz pencerelerden yararlanms.
Grdgnz gibi baslksz pencereler pek ok yerde isimize yarayabiliyor.
350
winfo_reqheight
winfo_reqwidth
winfo_rgb
winfo_rootx
winfo_rooty
winfo_screen
winfo_screencells
winfo_screendepth
winfo_screenheight
winfo_screenmmheight
winfo_screenmmwidth
winfo_screenvisual
winfo_screenwidth
winfo_server
winfo_toplevel
winfo_viewable
winfo_visual
winfo_visualid
winfo_visualsavailable
winfo_vrootheight
winfo_vrootwidth
winfo_vrootx
winfo_vrooty
winfo_width
winfo_x
winfo_y
Grdgnz gibi, elimizde epey metot var. Yukardaki kod yardmyla Tk() snf iindeki,
winfo ile baslayan btn metotlar listeledigimize dikkat edin... Biz bu blmde bu
metotlarn hepsini degil, bunlar arasnda en sk kullanlanlar inceleyecegiz. Inceleyecegimiz
metotlar sunlar olacak:
winfo_height
winfo_width
winfo_rootx
winfo_rooty
winfo_screenheight
winfo_screenwidth
winfo_x
winfo_y
351
winfo_height()
Bu metot, olusturdugumuz pencerenin (veya pencere aracnn) yksekligi hakknda bilgi verir
bize. Syle
Galiba bu kt pek fazla bir sey anlatmyor bize. Bu kodlardan byle bir kt almamzn
nedeni bir pencere ilk olusturuldugunda ykseklik degerinin 1 olarak kabul edilmesidir.
Eger pencerenin gerek boyutunu grmek istersek yukardaki kodlar su sekilde yazmamz
gerekir:
pencere = Tk()
pencere.update()
yukseklik = pencere.winfo_height()
print yukseklik
mainloop()
Burada da dgme bilgilerini gncellemek iin btn.update() gibi bir komuttan yararlandgmza
dikkat edin. Eger bu rnekte update() metodunu kullanmazsak biraz nce oldugu gibi,
alacagmz kt 1 olacaktr.
Elbette winfo_height() metodunu bir degiskene atamadan da kullanabiliriz. Ama akas o
sekilde pek pratik olmayacaktr...
Simdi
winfo_width()
Ilk inceledigimiz metot olan winfo_height, bir pencere veya pencere aracnn yksekligini
veriyordu. winfo_width() metodu ise pencere veya pencere aracnn genisligini verir. Hemen
grelim:
from Tkinter import *
pencere = Tk()
btn = Button(text="deneme")
btn.pack()
pencere.update()
genislik = pencere.winfo_width()
print genislik
mainloop()
Buradan aldgnz kt, pencerenin genisligini gsterir. Eger pencerenin degil de dgmenin
genisligini almak isterseniz ne yapmanz gerektigini tahmin edebilirsiniz:
from Tkinter import *
pencere = Tk()
btn = Button(text="deneme")
btn.pack()
btn.update()
genislik = btn.winfo_width()
print genislik
mainloop()
353
pencere = Tk()
pencere.geometry("200x200")
btn = Button(text="deneme")
btn.pack()
pencere.update()
xkoord = pencere.winfo_rootx()
print xkoord
mainloop()
Bu kodlar alstrdgmda ise konsolda 1027 ktsn grdm. Demek ki deneme adl
dgmenin sol kenar 1440x900lk monitrn 1027inci noktasna denk geliyormus...
winfo_rooty()
Bir nceki metodumuz olan winfo_rootx() x-koordinatlarnn bilgisini veriyordu.
winfo_rooty() ise y-koordinatlarnn bilgisini verir:
from Tkinter import *
pencere = Tk()
pencere.geometry("200x200")
btn = Button(text="deneme")
btn.pack()
pencere.update()
354
ykoord = pencere.winfo_rooty()
print ykoord
mainloop()
Buradan aldgmz sonu, pencerenin st snrnn y dzlemi zerinde hangi noktaya karslk
geldigini gsteriyor. Penceremiz ekrann en tepesinde bile olsa bu kodlar 0 veya 1 gibi bir
sonu vermez. nk pencere baslgnn hemen altndaki alann karslk geldigi nokta
hesaplanmaktadr. Bir de su rnege bakalm:
from Tkinter import *
pencere = Tk()
pencere.geometry("200x200")
btn = Button(text="deneme")
btn.pack(pady=30)
btn.update()
ykoord = btn.winfo_rooty()
print ykoord
mainloop()
Burada pady seenegini kullanarak dgmeyi biraz asagya kaydrdk ki bir nceki kodla
arasndaki fark grebilelim...
winfo_screenheight()
Bu metot ekran yksekliginin ka oldugunu syler. rnegin 1024x768lik bir znrlkte bu
metodun verdigi deger 768 olacaktr...
from Tkinter import *
pencere = Tk()
ekran_y = pencere.winfo_screenheight()
print ekran_y
mainloop()
winfo_screenwidth()
Bu metot da winfo_screenheight() metoduna benzer. Ama onun aksine, bir pencerenin
yksekligini degil, genisligini verir. Dolaysyla 1024x768lik bir ekran znrlgnde bu
deger 1024 olacaktr:
355
En nemli winfo metotlarn grdgmze gre bunlar kullanarak baz yararl isler
yapmaya baslayabiliriz...
356
programmzn ekran tam ortalayabilmesi iin ufak bir hesap yapmamz gerekecek...
x degerini bulabilmek iin ekran genisliginden programmzn pencere genisligini karp,
elde ettigimiz degeri ikiye blyoruz. Mesela eger kullandgmz ekran znrlg
1024x768 ise, x degeri syle olacaktr:
x = (1024 - 200) / 2
y degerini bulmak iin de benzer bir sekilde ekran yksekliginden program yksekligini
karp, bu degeri yine ikiye blyoruz. Dolaysyla y degeri 1024x768lik bir ekranda
syle olur:
y = (768 - 200) / 2
357
#!/usr/bin/env python
# -*- coding: utf-8 -*from Tkinter import *
from tkFileDialog import askopenfilename
pencere = Tk()
pgen = 200
pyuks = 200
ekrangen = pencere.winfo_screenwidth()
ekranyuks = pencere.winfo_screenheight()
x = (ekrangen - pgen) / 2
y = (ekranyuks - pyuks) / 2
pencere.geometry("%dx%d+%d+%d"%(pgen, pyuks, x, y))
def yeniPencere():
yeni = Toplevel()
xkonum = pencere.winfo_rootx()
ykonum = pencere.winfo_rooty()
yeni.geometry("+%d+%d"%(xkonum, ykonum))
ybtn = Button(yeni, text="Dosya a", command=yeniDosya)
ybtn.pack()
def yeniDosya():
dosya = askopenfilename()
btn = Button(pencere, text="yeni pencere a", command=yeniPencere)
btn.pack()
mainloop()
yeni.transient(pencere)
Yeni ekledigimiz satr, yeni adl ikinci pencerenin ana pencereye gre hep stte kalmasn
temin ediyor. Programmz bu sekilde alstrdgmzda her seyin olmas gerektigi gibi
oldugunu grecegiz. Kodlarmz bu sekilde yazdgmzda, ikinci pencereyi atktan sonra ana
pencereye tklasak bile ikinci pencere ana pencerenin arkasna dsmeyecektir.
359
BLM 23
360
pencere.mainloop()
Burada eger kullanc Entry() aracna herhangi bir sey yazmadan gnder dgmesine basarsa
bir uyar penceresi alacak ve kullancy Entry() aracna geerli bir e.posta yazmas
konusunda uyaracaktr.
Dedigimiz gibi, byle bir islev yerine getirmeniz gerekirse yukardaki yntemi
kullanabilirsiniz. Ama aslnda buna hi gerek yok. Tkinter bize bu tr isleri yapabilmemiz
iin bize baz aralar sunar. Iste biz de bu blmde Tkinterin bize sundugu bu aralar
inceleyecegiz.
Tkinterde kullancya bilgi mesaj gsteren btn pencereler tkMessageBox adl modln
iinde yer alyor. Dolaysyla bu pencereleri kullanmak istedigimizde, Tkinter modlyle
birlikte tkMessageBox modln de ie aktarmay unutmuyoruz.
Bir nceki blmde hatrlarsanz, kullancdan e.posta adresi girmesini istedigimiz ufak bir
uygulama yazmstk. Gelin isterseniz yine o rnek zerinden gidelim. ncelikle kodlarmzn
ne olduguna bakalm:
# -*- coding: utf-8 -*from Tkinter import *
pencere = Tk()
def kapat():
if not entry.get():
yenipen = Toplevel()
uyari = Label(yenipen)
uyari["text"] = "Ltfen geerli bir e.posta \
adresi yazn!"
uyari.pack()
uybtn = Button(yenipen)
uybtn["text"] = "Tamam"
uybtn["command"] = yenipen.destroy
uybtn.pack()
else:
pencere.destroy()
361
etiket = Label()
etiket["text"] = "e.posta adresiniz:"
etiket.pack()
entry = Entry()
entry.pack()
dgm = Button()
dgm["text"] = "Gnder"
dgm["command"] = kapat
dgm.pack()
pencere.mainloop()
Grdgnz gibi, aslnda basit bir is iin ok fazla kod yazmsz. Gelin bu kodlar,
tkMessageBox modlnn de yardmyla sadelestirelim ve hatta gzellestirelim:
# -*- coding: utf-8 -*from Tkinter import *
from tkMessageBox import *
pencere = Tk()
def kapat():
if not entry.get():
showerror("Hata!", "Ltfen geerli bir e.posta \
adresi girin!")
else:
pencere.destroy()
etiket = Label()
etiket["text"] = "e.posta adresiniz:"
etiket.pack()
entry = Entry()
entry.pack()
dgm = Button()
dgm["text"] = "Gnder"
dgm["command"] = kapat
dgm.pack()
pencere.mainloop()
Ne kadar hos, degil mi? Bu sekilde hem daha az kod yazms oluyoruz, hem de elde ettigimiz
kt daha oturmus bir grnme sahip. Dikkat ederseniz, hata mesajmz sevimli bir hata
simgesi de ieriyor. Bu hata penceresinin bize sagladklarn kendimiz yapmaya alsrsak
epey kod yazmamz gerekir. Dolaysyla yazacagmz programlarda byle bir imkanmzn
oldugunu da gz nnde bulundurmamz bizim iin faydal olacaktr.
362
Bir hata penceresinin sahip olmas gereken btn zellikleri tasyan bu hata penceresini su tek
satrlk kod yardmyla olusturduk:
showerror("Hata!", "Ltfen geerli bir e.posta adresi girin!")
zellikle Python kodlarna duyarl bir metin dzenleyici kullanyorsanz, (mesela IDLE)
virglden sonra ENTER tusuna bastgnzda metin dzenleyiciniz satrlar uygun sekilde
hizalayacaktr.
Elbette isterseniz daha estetik bir grnt elde etmek iin degiskenlerden de
faydalanabilirsiniz:
baslik = "Hata!"
mesaj = "Ltfen geerli bir e.posta adresi girin!"
detay = "e.posta adres uydurma olmasn!"
showerror(baslik, mesaj, detail = detay)
detail parametresi dsnda, showerror() fonksiyonu iin (ve tabii teki bilgi mesajlar iin)
kullanabilecegimiz baska parametreler de vardr. Mesela bu parametrelerden biri type
parametresidir. Bu parametre ile, bilgi ekrannda gsterilecek dgmelerin tipini
belirleyebiliriz. Bu parametre ile birlikte kullanabilecegimiz alt farkl seenek vardr:
ABORTRETRYIGNORE: Pencere zerinde vazge, tekrar dene, yoksay dgmelerini
gsterir.
OK: Pencere zerinde tamam dgmesi gsterir.
OKCANCEL: Pencere zerinde tamam ve iptal dgmelerini gsterir.
RETRYCANCEL: Pencere zerinde yeniden dene ve iptal dgmelerini gsterir.
YESNO: Pencere zerinde evet ve hayr dgmelerini gsterir.
YESNOCANCEL: Pencere zerinde evet, hayr ve iptal dgmelerini gsterir.
23.1. Hata Mesaj Gsteren Pencere
363
En son parametremiz ise icon adl olan. Bu parametre yardmyla, bilgi penceresi zerinde
grdgmz simgenin trn belirleyebiliriz. Bu parametre ile su seenekleri kullanabiliriz:
ERROR (Hata simgesi)
INFO (Bilgi simgesi)
QUESTION (Soru simgesi)
WARNING (Uyar simgesi)
Bu parametreyi ise syle kullanacagz:
Bu arada, mmkn olan yerlerde kod satrlarmz yukarda gibi uzun tutmamak iyi bir
yaklasm olacaktr. Dolaysyla yukardaki satr biraz daha blmek okunakllg artrr:
showerror(baslik,
mesaj,
detail = detay,
type = ABORTRETRYIGNORE,
default=RETRY,
icon=WARNING)
Peki, kullanc bu bilgi ekranndaki herhangi bir dgmeye bastgnda hangi islemin
yaplacagn nasl belirleyecegiz? Yani mesela diyelim ki kullanc OK tusuna bast, iste
364
byle bir durumda hangi islemin yaplmas gerektigini nasl bulacagz? Bu isi yapmakta
olduka kolaydr. Hemen syle bir rnek verelim:
# -*- coding: utf-8 -*from Tkinter import *
from tkMessageBox import *
pencere = Tk()
def soru():
cevap = showerror("Uyar",
"Bu i
slem diskteki btn verileri silecektir.",
type=OKCANCEL)
if cevap == "ok":
etiket["text"] = "disk biimlendirildi!"
if cevap == "cancel":
etiket["text"] = "i
slem durduruldu!"
etiket = Label(text="i
slem durumu: ")
etiket.pack()
dgm = Button(text="diski biimlendir!", command=soru)
dgm.pack()
mainloop()
365
dgm.pack()
mainloop()
Elbette burada ktlar konsola veriyoruz. Ama eger siz isterseniz arayz zerindeki Label()
aracnn text seenegine de bu ktlar yazdrabilirsiniz:
from Tkinter import *
from tkMessageBox import *
pencere = Tk()
def soru():
cevap = showerror("Uyar",
"Bu i
slem diskteki btn verileri silecektir.",
type=ABORTRETRYIGNORE)
etiket["text"] = cevap
etiket = Label()
etiket.pack()
dgm = Button(text="diski biimlendir!", command=soru)
dgm.pack()
mainloop()
Grdgnz gibi, showerror() fonksiyonunu kullanmak zor degil. Gelin isterseniz simdi teki
bilgi pencerelerine de syle bir gz atalm.
366
if not entry.get():
showerror("Hata!", "rn says belirtmediniz!")
return "break"
try:
int(entry.get())
showinfo("Bilgi", "%s rn sepete eklendi!"%entry.get())
except ValueError:
showerror("Hata!", "Ltfen bir say girin!")
etiket = Label()
etiket["text"] = "rn adedi:"
etiket.pack()
entry = Entry()
entry.pack()
dgm = Button()
dgm["text"] = "Gnder"
dgm["command"] = kapat
dgm.pack()
pencere.mainloop()
Burada birka islemi ayn anda yaptk. Programmzn amac, kullancnn kutucuga bir say
yazmasn saglamak. Ayrca kullancnn, kutucuga hi bir sey yazmadan Gnder tusuna
basabilecegini de hesaba katmamz gerekir... Byle bir duruma kars, kodlarmz iinde su
satrlar yazdk:
if not entry.get():
showerror("Hata!", "rn says belirtmediniz!")
return "break"
Eger kullancmz, kutucugu bos brakrsa kendisine bir hata mesaj gsteriyoruz. Burada
return break ifadesini kullanmamzn nedeni, hata mesaj gsterildikten sonra programn
alsmaya devam etmesini engellemek. Eger bu ifadeyi yazmazsak, programmz kullancya
hata mesaj gsterdikten sonra alt satrdaki kodlar da isletmeye devam edecektir. Isterseniz o
satr kaldrp kendi kendinize birtakm denemeler yapabilirsiniz...
Bildigimiz gibi, entry.get() metodundan elde edilen verinin tipi karakter dizisidir. Kullancnn
bir say m yoksa bir harf mi girdigini tespit edebilmek iin ncelikle, kutucuga kullanc
tarafndan yazlan degerin sayya dnstrlebilen bir veri olup olmadgna bakyoruz. Bunun
iin su kodlar yazdk:
try:
int(entry.get())
showinfo("Bilgi", "%s rn sepete eklendi!"%entry.get())
except ValueError:
showerror("Hata!", "Ltfen bir say girin!")
Burada eger kullancnn yazdg sey sayya dnstrlebilen bir veri ise kendisine showinfo()
fonksiyonunu kullanarak ka rnn sepete eklendigi bilgisini veriyoruz. Ama eger mesela
kullanc say girmek yerine fsdfd gibi bir sey yazarsa, bu defa showerror() fonksiyonunu
23.2. Bilgi Mesaj Gsteren Pencere
367
kullanarak ona, say girmedigine dair bir hata mesaj gsteriyoruz. Burada try except
bloklarn nasl kullandgmza dikkat edin...
Grdgnz gibi, showinfo() fonksiyonunun kullanm showerror() fonksiyonunun
kullanmna ok benziyor. Hatta hemen hemen ayn bile diyebiliriz...
Geen blmde showerror() fonksiyonunu islerken, bu fonksiyonun birtakm parametreler de
alabildigini sylemistik. Orada sylediklerimiz showinfo() fonksiyonu iin de geerlidir.
Mesela burada da detail parametresini kullanarak, kullancya konuyla ilgili ek bilgi
verebiliriz:
showinfo("Bilgi", "%s rn sepete eklendi!"%entry.get(),
detail="Ama bu kadar rn az!\nrnlerimizden \
biraz daha aln!")
showerror() ile showinfo() arasndaki benzerlikler bununla da snrl degildir. Mesela geen
blmde grendigimiz type parametresini burada da kullanabiliriz:
showinfo(Bilgi, %s rn sepete eklendi!%entry.get(), detail=Ama bu kadar rn
az!nrnlerimizden biraz daha aln!, type=OKCANCEL)
Grdgnz gibi, showerror() konusunda ne grendiysek burada da uygulayabiliyoruz.
Isterseniz geen blmde grendigimiz bilgileri showinfo() fonksiyonuna da uygulayarak
kendi kendinize el alstrmalar yapabilirsiniz.
Sra geldi baska bir bilgi mesaj penceresini incelemeye...
368
entry.pack()
dgm = Button()
dgm["text"] = "Gnder"
dgm["command"] = kapat
dgm.pack()
pencere.mainloop()
369